最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python自動重新加載模塊詳解(autoreload module)

 更新時間:2020年04月01日 10:11:01   作者:promissing  
這篇文章主要介紹了Python自動重新加載模塊詳解(autoreload module),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

守護進程模式

使用python開發(fā)后臺服務(wù)程序的時候,每次修改代碼之后都需要重啟服務(wù)才能生效比較麻煩。

看了一下Python開源的Web框架(Django、Flask等)都有自己的自動加載模塊功能(autoreload.py),都是通過subprocess模式創(chuàng)建子進程,主進程作為守護進程,子進程中一個線程負責檢測文件是否發(fā)生變化,如果發(fā)生變化則退出,主進程檢查子進程的退出碼(exist code)如果與約定的退出碼一致,則重新啟動一個子進程繼續(xù)工作。

自動重新加載模塊代碼如下:

autoreload.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This module is used to test how to reload the modules automatically when any
changes is detected.
"""
__author__="Wenjun Xiao"

import os,sys,time,subprocess,thread

def iter_module_files():
 for module in sys.modules.values():
  filename = getattr(module, '__file__', None)
  if filename:
   if filename[-4:] in ('.pyo', '.pyc'):
    filename = filename[:-1]
   yield filename

def is_any_file_changed(mtimes):
 for filename in iter_module_files():
  try:
   mtime = os.stat(filename).st_mtime
  except IOError:
   continue
  old_time = mtimes.get(filename, None)
  if old_time is None:
   mtimes[filename] = mtime
  elif mtime > old_time:
   return 1
 return 0

def start_change_detector():
 mtimes = {}
 while 1:
  if is_any_file_changed(mtimes):
   sys.exit(3)
  time.sleep(1)

def restart_with_reloader():
 while 1:
  args = [sys.executable] + sys.argv
  new_env = os.environ.copy()
  new_env['RUN_FLAG'] = 'true'
  exit_code = subprocess.call(args, env=new_env)
  if exit_code != 3:
   return exit_code

def run_with_reloader(runner):
 if os.environ.get('RUN_FLAG') == 'true':
  thread.start_new_thread(runner, ())
  try:
   start_change_detector()
  except KeyboardInterrupt:
   pass
 else:
  try:
   sys.exit(restart_with_reloader())
  except KeyboardInterrupt:
   pass

測試的主模塊如下:

runner.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Runner for testing autoreload module."""

__author__="Wenjun Xiao"

import os,time

def runner():
 print "[%s]enter..." % os.getpid()
 while 1:
  time.sleep(1)
 print "[%s]runner." % os.getpid()

if __name__ == '__main__':
 from autoreload import run_with_reloader
 run_with_reloader(runner)

運行runner.py:

promissing@ubuntu:python-autoreload$ python runner.py
[11743]enter...

主程序已經(jīng)運行,只不過是一致在循環(huán),可以查看此時有兩個進程:

promissing@ubuntu:~$ ps -aux|grep runner[.py]
promiss+ 11742 0.0 0.2 10928 4208 pts/0 S+ 19:34 0:00 python runner.py
promiss+ 11743 0.0 0.1 20152 4092 pts/0 Sl+ 19:34 0:00 /usr/bin/python runner.py

在編輯器中打開runner.py做一些可見的修改(增加一條打印語句)如下:

# runner.py
...
def runner():
 print "[%s]enter..." % os.getpid()
 print "[%s]Runner has changed." % os.getpid()
 while 1:
  time.sleep(1)
 print "[%s]runner." % os.getpid()
...

保存之后查看運行運行情況:

promissing@ubuntu:python-autoreload$ python runner.py 
[11743]enter...
[11772]enter...
[11772]Runner has changed.

可以看到新增的語句已經(jīng)生效,繼續(xù)看進程情況:

promissing@ubuntu:~$ ps -aux|grep runner[.py]
promiss+ 11742 0.0 0.2 10928 4220 pts/0 S+ 19:34 0:00 python runner.py
promiss+ 11772 0.0 0.1 20152 4092 pts/0 Sl+ 19:37 0:00 /usr/bin/python runner.py

可以對比兩次的進程,可以看到使用守護進程模式可以簡單的實現(xiàn)模塊自動重新加載功能。

使用守護進程模式,有一種情況比較麻煩:如果主進程由于其他原因退出了,那么子進程還在運行:

promissing@ubuntu:~$ kill 11742
promissing@ubuntu:~$ ps -aux|grep runner[.py]
promiss+ 11772 0.0 0.1 20152 4092 pts/0 Sl 19:37 0:00 /usr/bin/python runner.py

為了重啟服務(wù)還需要通過其他方式找到子進程并結(jié)束它可以。

守護進程模式-退出問題

為了解決由于守護進程退出,而導致子進程沒有退出的問題,一種比較簡單的解決方法就是在守護進程退出的時候也把子進程結(jié)束:

# autoreload.py
...
import signal
...
_sub_proc = None

def signal_handler(*args):
 global _sub_proc
 if _sub_proc:
  print "[%s]Stop subprocess:%s" % (os.getpid(), _sub_proc.pid)
  _sub_proc.terminate()
 sys.exit(0)

def restart_with_reloader():
 signal.signal(signal.SIGTERM, signal_handler) 
 while 1:
  args = [sys.executable] + sys.argv
  new_env = os.environ.copy()
  new_env['RUN_FLAG'] = 'true'
  global _sub_proc
  _sub_proc = subprocess.Popen(args, env=new_env)
  exit_code = _sub_proc.wait()
  if exit_code != 3:
   return exit_code
...

運行,查看效果(這次沒有測試修改):

promissing@ubuntu:python-autoreload$ python runner.py
[12425]enter...
[12425]Runner has changed.
[12424]Stop subprocess:12425

另一個控制臺執(zhí)行的命令如下:

promissing@ubuntu:~$ ps -aux|grep runner[.py]
promiss+ 12424 0.2 0.2 10928 4224 pts/0 S+ 20:26 0:00 python runner.py
promiss+ 12425 0.2 0.1 20152 4092 pts/0 Sl+ 20:26 0:00 /usr/bin/python runner.py
promissing@ubuntu:~$ kill 12424
promissing@ubuntu:~$ ps -aux|grep runner[.py]
promissing@ubuntu:~$ 

已經(jīng)達到我們需要的功能了嗎?等等,在控制臺上運行工程總是能很好的工作,如果是在IDE中呢?由于IDE中輸入輸出是重定向處理的,比如,在Sublime中就沒有辦法獲取到輸出信息。

因此還需要進一步完善輸出的問題。

守護進程模式-輸出問題

解決輸出問題,也很簡單,修改如下:

# autoreload.py
...
def restart_with_reloader():
 signal.signal(signal.SIGTERM, signal_handler)
 while 1:
  args = [sys.executable] + sys.argv
  new_env = os.environ.copy()
  new_env['RUN_FLAG'] = 'true'
  global _sub_proc
  _sub_proc = subprocess.Popen(args, env=new_env, stdout=subprocess.PIPE,
   stderr=subprocess.STDOUT)
  read_stdout(_sub_proc.stdout)
  exit_code = _sub_proc.wait()
  if exit_code != 3:
   return exit_code

...
def read_stdout(stdout):
 while 1:
  data = os.read(stdout.fileno(), 2**15)
  if len(data) > 0:
   sys.stdout.write(data)
  else:
   stdout.close()
   sys.stdout.flush()
   break

經(jīng)過以上修改,也適合在IDE中使用守護進程模式了。

源代碼:https://github.com/wenjunxiao/python-autoreload

以上這篇Python自動重新加載模塊詳解(autoreload module)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論

临沭县| 河曲县| 麟游县| 岱山县| 禹州市| 屏边| 莆田市| 上杭县| 通许县| 西吉县| 遵义市| 关岭| 城市| 永宁县| 黑水县| 松滋市| 玉门市| 疏勒县| 湄潭县| 福州市| 海城市| 册亨县| 建瓯市| 长汀县| 巴里| 苍梧县| 福安市| 周至县| 南乐县| 柏乡县| 库车县| 瑞金市| 永仁县| 长岭县| 潢川县| 合肥市| 高台县| 文成县| 临高县| 曲阜市| 华池县|