[英]How to use a Python script to start and stop a Python script containing “http.server.serveforever”
背景
我有一个名为server.py
的Python 3脚本,它使用内置的http.server
模块。 该脚本可归结为以下内容:
from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
class MyRequestHandler (BaseHTTPRequestHandler):
def do_POST(self):
# Code omitted for brevity
def do_GET(self):
# Code omitted for brevity
def start_server():
# Begin serving
# -------------
server = HTTPServer(('', port), MyRequestHandler)
print("server now running on port {0} ...".format(port))
server.serve_forever()
# Start the Server
# ----------------
if __name__ == '__main__':
start_server()
MyRequestHandler
通过“即时”导入模块来处理GET和POST请求,具体取决于用于请求的URI。
上面的方法工作正常,但是,在创建该脚本之后,需要能够远程更新脚本的整个“包”(即服务器脚本以及已加载的所有“模块脚本”即时”,位于子文件夹中)。
为此,我在Python 3中编写了另一个服务器脚本(称为updater.py
),该脚本将在得到指示时检索一个zip文件,然后将其解压缩以覆盖原始的server.py
脚本以及所有其他相关的脚本和子脚本。 -文件夹。
题
这一切都很好,但是我现在碰壁了。 我认为,最好的方法是让updater.py
脚本控制server.py
的运行。 它可以关闭server.py
以及与其链接的所有内容,然后再覆盖所有内容,然后在覆盖后重新启动它。
在此基础上,我走过的路是使用subprocess.Popen
启动服务器,认为我可以在覆盖server.py
之前杀死Python进程,但是,这并没有达到预期的效果。 这是我为测试该理论而编写的trial.py
脚本:
import sys
import subprocess
def main():
def start_process():
proc = subprocess.Popen([sys.executable, 'server.py'])
print("Started process:")
print(proc.pid)
return proc
def kill_process(the_process):
print("Killing process:")
print(the_process.pid)
the_process.kill()
process = None
while True:
user_input = input("Type something: ")
if user_input == 'start':
process = start_process()
if user_input == 'kill':
kill_process(process)
if user_input == 'exit':
break
if __name__ == '__main__':
main()
这似乎确实可以启动并杀死一个Python进程,但是此脚本在运行时服务器未在运行,因此我不确定它正在启动并终止什么! 键入“开始”然后“退出”(从而退出trial.py
脚本)将允许服务器运行,尽管我不明白为什么,因为我认为subprocess.Popen
应该导致生成的进程独立于父进程运行处理?
编辑:由于下面@HåkenLid的敏锐观察,我注意到我所做的一切只是打破了while
循环, 而不是退出脚本。 这使我相信while
循环以某种方式阻止了子进程的运行(因为一旦退出循环,服务器将启动)。
根据我们的讨论,我建议使用某种方法从“ server.py”中清空stdio缓冲区。 如果还希望能够提供用户输入,则在等待用户在主线程上输入时,需要一个线程来进行打印(或只是将缓冲区清空到黑洞中)。 这是我可能如何做的一个大概想法。
import sys
import subprocess
from threading import Thread
#This could probably be solved with async, but I still
#haven't learned async as well as I know threads
def main():
def start_process():
proc = subprocess.Popen([sys.executable, 'server.py'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
print("Started process:")
def buf_readerd(proc, inbuf, outbuf):
while proc.poll() is None:
outbuf.write(inbuf.readline()) #may need to add a newline.. I'm not sure if readline ends in a \n
stdoutd = Thread(target=buf_readerd, args=(proc, proc.stdout, sys.stdout), daemon=True)
stderrd = Thread(target=buf_readerd, args=(proc, proc.stderr, sys.stderr), daemon=True)
stdoutd.start()
stderrd.start()
print("started pipe reader daemons")
print(proc.pid)
return proc
# ...
好的,我想我已经自己修复此问题。 问题是我在while
循环内通过调用input()
阻止了子流程的执行。 在收到一些输入之前,脚本不执行任何操作。 我使subprocess.poll()
成为循环的组成部分,并将对input()
的调用置于该循环内。 如果几次击<return>
,服务器将启动并且可以使用它。 如果再键入kill
,则服务器将按预期终止。
我不确定在我的updater.py
脚本的上下文中这将如何工作,但是我已经学到了一个有价值的课程,即“在发布到StackOverflow之前要更深入地思考”!
import sys
import subprocess
def main():
def start_process():
proc = subprocess.Popen([sys.executable, 'server.py'])
print("Started process:")
print(proc.pid)
return proc
def kill_process(the_process):
print("Killing process:")
print(the_process.pid)
the_process.kill()
user_input = input("Type something: ")
if user_input == 'start':
process = start_process()
while process.poll() is None:
user_input = input()
if user_input == 'kill' or user_input == 'exit':
kill_process(process)
if __name__ == '__main__':
main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.