用Python實現伺服器中只重載被修改的進程的方法

來源:互聯網
上載者:User
現在,我們已經把一個Web App的架構完全搭建好了,從後端的API到前端的MVVM,流程已經跑通了。

在繼續工作前,注意到每次修改Python代碼,都必須在命令列先Ctrl-C停止伺服器,再重啟,改動才會生效。

在開發階段,每天都要修改、儲存幾十次代碼,每次儲存都手動來這麼一下非常麻煩,嚴重地降低了我們的開發效率。有沒有辦法讓伺服器檢測到代碼修改後自動重新載入呢?

Django的開發環境在Debug模式下就可以做到自動重新載入,如果我們編寫的伺服器也能實現這個功能,就能大大提升開發效率。

可惜的是,Django沒把這個功能獨立出來,不用Django就享受不到,怎麼辦?

其實Python本身提供了重新載入模組的功能,但不是所有模組都能被重新載入。另一種思路是檢測www目錄下的代碼改動,一旦有改動,就自動重啟伺服器。

按照這個思路,我們可以編寫一個輔助程式pymonitor.py,讓它啟動wsgiapp.py,並時刻監控www目錄下的代碼改動,有改動時,先把當前wsgiapp.py進程殺掉,再重啟,就完成了伺服器處理序的自動重啟。

要監控目錄檔案的變化,我們也無需自己手動定時掃描,Python的第三方庫watchdog可以利用作業系統的API來監控目錄檔案的變化,並發送通知。我們先用easy_install安裝:

$ easy_install watchdog

利用watchdog接收檔案變化的通知,如果是.py檔案,就自動重啟wsgiapp.py進程。

利用Python內建的subprocess實現進程的啟動和終止,並把輸入輸出重新導向到當前進程的輸入輸出中:

#!/usr/bin/env pythonimport os, sys, time, subprocessfrom watchdog.observers import Observerfrom watchdog.events import FileSystemEventHandlerdef log(s):  print '[Monitor] %s' % sclass MyFileSystemEventHander(FileSystemEventHandler):  def __init__(self, fn):    super(MyFileSystemEventHander, self).__init__()    self.restart = fn  def on_any_event(self, event):    if event.src_path.endswith('.py'):      log('Python source file changed: %s' % event.src_path)      self.restart()command = ['echo', 'ok']process = Nonedef kill_process():  global process  if process:    log('Kill process [%s]...' % process.pid)    process.kill()    process.wait()    log('Process ended with code %s.' % process.returncode)    process = Nonedef start_process():  global process, command  log('Start process %s...' % ' '.join(command))  process = subprocess.Popen(command, stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr)def restart_process():  kill_process()  start_process()def start_watch(path, callback):  observer = Observer()  observer.schedule(MyFileSystemEventHander(restart_process), path, recursive=True)  observer.start()  log('Watching directory %s...' % path)  start_process()  try:    while True:      time.sleep(0.5)  except KeyboardInterrupt:    observer.stop()  observer.join()if __name__ == '__main__':  argv = sys.argv[1:]  if not argv:    print('Usage: ./pymonitor your-script.py')    exit(0)  if argv[0]!='python':    argv.insert(0, 'python')  command = argv  path = os.path.abspath('.')  start_watch(path, None)

一共50行左右的代碼,就實現了Debug模式的自動重新載入。用下面的命令啟動伺服器:

$ python pymonitor.py wsgiapp.py

或者給pymonitor.py加上可執行許可權,啟動伺服器:

$ ./pymonitor.py wsgiapp.py

在編輯器中開啟一個py檔案,修改後儲存,看看命令列輸出,是不是自動重啟了伺服器:

$ ./pymonitor.py wsgiapp.py [Monitor] Watching directory /Users/michael/Github/awesome-python-webapp/www...[Monitor] Start process python wsgiapp.py......INFO:root:application (/Users/michael/Github/awesome-python-webapp/www) will start at 0.0.0.0:9000...[Monitor] Python source file changed: /Users/michael/Github/awesome-python-webapp/www/apis.py[Monitor] Kill process [2747]...[Monitor] Process ended with code -9.[Monitor] Start process python wsgiapp.py......INFO:root:application (/Users/michael/Github/awesome-python-webapp/www) will start at 0.0.0.0:9000...Try
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.