簡體   English   中英

如何使用Python腳本啟動和停止包含“ http.server.serveforever”的Python腳本

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM