web.py + subprocess = 卡住

2 投票
2 回答
1261 浏览
提问于 2025-04-16 11:59

这是我的主文件:

import subprocess, time

pipe = subprocess.PIPE
popen = subprocess.Popen('pythonw -uB test_web_app.py', stdout=pipe)
time.sleep(3)

这是 test_web_app.py 文件:

import web

class Handler:
  def GET(self):  pass
app = web.application(['/', 'Handler'], globals())
app.run()

当我运行主文件时,程序会执行,但会留下一个僵尸进程,我必须手动结束它。这是为什么呢?我该如何让 Popen 在程序结束时也结束?只有在我将输出重定向并在程序结束前稍微等待一下时,Popen 才会挂起。

编辑 -- 这是主文件的最终工作版本:

import subprocess, time, atexit

pipe = subprocess.PIPE
popen = subprocess.Popen('pythonw -uB test_web_app.py', stdout=pipe)

def kill_app():
  popen.kill()
  popen.wait()
atexit.register(kill_app)

time.sleep(3)

相关问题:

2 个回答

1

如果你的主程序在子程序执行的时候不需要做其他事情,我建议你可以这样做:

import subprocess, time

pipe = subprocess.PIPE
popen = subprocess.Popen('pythonw -uB test_web_app.py', stdout=pipe, stderr=pipe)
out, err = popen.communicate()

(我觉得如果你特别把输出结果(stdout)传回你的程序,你需要在某个时候读取它,以避免产生僵尸进程——使用 communicate 方法可以安全地读取这些输出。)

或者如果你不在乎解析输出结果(stdout)和错误信息(stderr),那就不用管它们的传递了:

popen = subprocess.Popen('pythonw -uB test_web_app.py')
popen.communicate()
2

你还没有等待这个进程完成。一旦它结束,你需要调用popen.wait

你可以使用popen对象的poll方法来检查这个进程是否已经结束。

如果你不需要网页服务器进程的输出,可以直接忽略stdout这个选项。


你可以使用atexit模块来实现一个钩子,这个钩子会在你的主文件退出时被调用。这个钩子应该使用Popen对象的kill方法,然后再调用wait来确保它已经被终止。

撰写回答