当前位置: 首页 > 知识库问答 >
问题:

如何使用Python脚本启动和停止包含"http.server.serveforever"的Python脚本

裴展
2023-03-14

背景资料

我有一个名为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()

根据用于请求的URI,通过动态导入模块来处理GET和POST请求。

上面的工作正常,但是,在创建脚本之后,需要能够远程更新脚本的整个“包”(即服务器脚本,加上所有“动态加载”的“模块脚本””并位于子文件夹中)。

为此,我在Python 3中编写了另一个服务器脚本(称为updater.py),当被指示时,它将检索一个zip文件,然后将其解压缩以覆盖原始的server.py脚本与所有其他相关的脚本和子文件夹。

问题

这一切都很好,但我现在遇到了麻烦。我认为最好的方法是让updater.py脚本控制server.py的运行。它可以关闭服务器.py,并在覆盖它之前关闭所有链接到它的东西,然后在覆盖它之后给它一个干净的开始。

在此基础上,我所走的路就是使用子进程。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进程,但是在这个脚本运行时服务器没有运行,所以我不确定它启动和终止的是什么!输入“start”然后输入“exit”(从而退出trial.py脚本)允许服务器运行,尽管我不明白为什么,因为我认为subprocess.Popen应该导致生成的进程独立于父进程运行?

编辑:多亏@Håken Lid在下面敏锐的观察,我注意到我所做的一切都是在过程中突破循环,而不是退出脚本。这使我相信while循环以某种方式阻止了子进程的运行(因为一旦退出循环,服务器就会启动)。


共有2个答案

柳弘方
2023-03-14

好吧,所以我想我现在已经自己解决了。问题是,我阻止了子进程执行与调用输入()内的循环。在收到一些输入之前,脚本什么也不做。我使subprocess.poll()成为循环的一个组成部分,并在这个循环中调用输入()。如果我按了

我不确定这将如何在我的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()

薛经纶
2023-03-14

根据我们的讨论,我建议使用某种方法从“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
# ...
 类似资料:
  • 问题内容: 我有一个简单的python脚本,我需要启动和停止,我需要使用start.sh和stop.sh脚本来执行此操作。 我有start.sh: 和stop.sh 我主要关注stop.sh脚本。我 认为 这是找到pid的适当方法,但我对此并不敢多说。start.sh成功启动它。当我运行stop.sh时,我无法再通过控制台找到该进程,但输出如下: 因此似乎可以正常工作,并显示“没有这样的过程”的错

  • 我为浏览器游戏制作了脚本。在这个游戏中,我站着不动,我的脚本在某些地方点击bksononechno,但我需要的是,如果我点击字母,这个脚本将自杀,而不是试图关闭浏览器及其在浏览器中的选项卡和类似的东西。 抱歉出错了。

  • 问题内容: 我用IDLE编写了一个程序来标记文本文件,然后开始标记349个文本文件!我该如何阻止它?如何停止正在运行的Python程序? 问题答案: 要停止程序,只需按 + 。

  • 我写了一个程序在IDLE令牌化文本文件,它开始令牌349文本文件!我怎样才能阻止它?如何停止正在运行的Python程序?

  • 背景: 我有一个运行的python脚本。它包含许多在循环中调用。 如果我按ctrlC,它只是停止执行当前的并传递到下一个。 问题: 如何停止整个脚本的执行,而不仅仅是当前调用的可执行文件的执行? 请注意,我已经仔细阅读了这里的问题/答案,但是即使使用,我也可以杀死可执行文件,但不能杀死整个脚本(我无法使用找到)。 我必须停止脚本(不重新启动系统)的唯一方法是继续在循环中按ctrl C,直到所有测试

  • 问题内容: 我写了Python脚本来处理大量的大文本文件,并且可能 要花费很多时间 。有时,需要停止正在运行的脚本并在以后恢复它。停止脚本的可能原因是程序崩溃,磁盘空间不足或需要执行此操作的其他原因。我想为脚本实现一种“停止/恢复”机制。 在 车站 :脚本退出和保存其当前状态。 在 简历 :剧本开始,但是从最新的保存状态持续 我将使用 pickle 和 信号 模块来实现它。 我将很高兴听到如何以p