[英]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.