在開發和除錯wsgi應用程式時,有很多方法可以自動重新載入程式碼。例如,如果你使用的是werkzeug
,則只需要傳use_reloader
引數即可:
run_sumple('127.0.0.1', 5000, app, use_reloader=True)
複製程式碼
對於Flask,實際上在內部使用werkzeug,所以你需要設定debug = true:
app.run(debug=True)
複製程式碼
django會在你修改任何程式碼的時候自動為你重新載入:
python manage.py runserver
複製程式碼
所有這些例子在本地開發的時候都非常有用,但是,建議不要在實際生產中使用。
作為學習,可以一起來看一下,python是如何讓程式碼自動地重新載入的?
uWSGI
如果使用的是 uwsgi
和 django
,實際上可以直接通過程式碼跳轉檢視一下 django
本身的自動過載機制:
import uwsgi
from uwsgidecorators import timer
from django.utils import autoreload
@timer(3)
def change_code_gracefull_reload(sig):
if autoreload.code_changed():
uwsgi.reload()
複製程式碼
可以看出,django
通過一個定時器在不斷的監測程式碼是否有變化,以此來出發重新載入函式。
如果你使用的是其他框架,或者根本沒有框架,那麼可能就需要在應用程式中自己來實現程式碼改動監測。這裡是一個很好的示例程式碼,借用和修改自 cherrypy:
import os, sys
_mtimes = {}
_win = (sys.platform == "win32")
_error_files = []
def code_changed():
filenames = []
for m in sys.modules.values():
try:
filenames.append(m.__file__)
except AttributeError:
pass
for filename in filenames + _error_files:
if not filename:
continue
if filename.endswith(".pyc") or filename.endswith(".pyo"):
filename = filename[:-1]
if filename.endswith("$py.class"):
filename = filename[:-9] + ".py"
if not os.path.exists(filename):
continue # File might be in an egg, so it can't be reloaded.
stat = os.stat(filename)
mtime = stat.st_mtime
if _win:
mtime -= stat.st_ctime
if filename not in _mtimes:
_mtimes[filename] = mtime
continue
if mtime != _mtimes[filename]:
_mtimes.clear()
try:
del _error_files[_error_files.index(filename)]
except ValueError:
pass
return True
return False
複製程式碼
你可以將上面的內容儲存在你的專案中的 autoreload.py
中,然後我們就可以像下面這樣去呼叫它(類似於 django
的例子):
import uwsgi
from uwsgidecorators import timer
import autoreload
@timer(3)
def change_code_gracefull_reload(sig):
if autoreload.code_changed():
uwsgi.reload()
複製程式碼
gunicorn
對於 gunicorn
,我們需要寫一個指令碼來 hook(鉤子:觸發)
到 gunicorn
的配置中:
import threading
import time
try:
from django.utils import autoreload
except ImportError:
import autoreload
def reloader(server):
while True:
if autoreload.code_changed():
server.reload()
time.sleep(3)
def when_ready(server):
t = threading.Thread(target=reloader, args=(server, ))
t.daemon = True
t.start()
複製程式碼
你需要把上面的程式碼儲存到一個檔案中,比如說 config.py
,然後像下面這樣傳給 gunicorn
:
gunicorn -c config.py application
複製程式碼
外部解決方法
你也可以通過正在使用的 wsgi
服務系統本身以外的一些方法來實現重啟系統,它只需發出一個訊號,告訴系統重啟程式碼,比如可以使用 watchdog。例如:
watchmedo shell-command --patterns="*.py" --recursive --command='kill -HUP `cat /tmp/gunicorn.pid`' /path/to/project/
複製程式碼
轉載請保留以下資訊: