还是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并退出