还是run函数,本节主要分析reload机制,下面是生成临时锁文件,并生成子线程运行服务代码
def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, interval=1, reloader=False, quiet=False, plugins=None, debug=None, **kargs): if NORUN: return if reloader and not os.environ.get('BOTTLE_CHILD'): try: lockfile = None fd, lockfile = tempfile.mkstemp(prefix='bottle.', suffix='.lock') os.close(fd) # We only need this file to exist. We never write to it while os.path.exists(lockfile): args = [sys.executable] + sys.argv environ = os.environ.copy() environ['BOTTLE_CHILD'] = 'true' environ['BOTTLE_LOCKFILE'] = lockfile p = subprocess.Popen(args, env=environ) while p.poll() is None: # Busy wait... os.utime(lockfile, None) # I am alive! time.sleep(interval) if p.poll() != 3: if os.path.exists(lockfile): os.unlink(lockfile) sys.exit(p.poll()) except KeyboardInterrupt: pass finally: if os.path.exists(lockfile): os.unlink(lockfile) return
安全地址创建临时文件
fd, lockfile = tempfile.mkstemp(prefix='bottle.', suffix='.lock')
prefix为前缀,suffix为后缀
返回一个元组,fd为文件句柄,lockfile为文件路径
os.close(fd)
因为后面只需要用lockfile来监测文件是否存在,所以关闭句柄
args = [sys.executable] + sys.argv
如果我的主运行脚本路径为,
则sys.argv为/usr/app/main.py
python执行路径为/usr/local/bin/python
则args 为["/usr/local/bin/python", "/usr/app/main.py"]
environ = os.environ.copy() environ['BOTTLE_CHILD'] = 'true' environ['BOTTLE_LOCKFILE'] = lockfile p = subprocess.Popen(args, env=environ)
为了不影响主进程的环境变量,复制一份环境变量并增加两个KEY传递给子进程。
如果不指定env,则会自动继承当前进程的env
通过subprocess.Popen返回Popen对象p
while p.poll() is None: # Busy wait... os.utime(lockfile, None) # I am alive! time.sleep(interval) if p.poll() != 3: if os.path.exists(lockfile): os.unlink(lockfile) sys.exit(p.poll())
while p.poll() is None: 通过while循环判断子进程是否执行中,如果是None,则正在执行中,因为服务器进程一般来说是run_forever的。
os.utime(lockfile, None) 设置lockfile的修改时间为当前时间
if p.poll() != 3: 为什么要定义3呢?是由于后面有段代码指定,如果退出符号为3,即视为需要重新reload
if bgcheck.status == 'reload': sys.exit(3)
如果产生的非3的返回值,则删除lockfile并退出