Popen
url_arg = "http://localhost/index.html?someparam=somevalue"
call = ('phantomjs', 'some/phantom/script.js', url_arg)

imageB64data = tempfile.TemporaryFile()
errordata = tempfile.TemporaryFile()

p = Popen(call, stdout=imageB64data, stderr=errordata, stdin=PIPE)
p.communicate(input="")

我看到了一些间歇性的问题,在这些
Popen
事件发生后(大约64个),进程耗尽了文件描述符,无法运行——它变得完全没有响应,如果所有线程试图打开任何文件或套接字,它们似乎会永远阻塞。
(可能相关:
phantomjs
子进程将URL调用加载回生成它的服务器。)
基于this Python bug report,我认为需要对服务器进程内的所有
close_fds=True
调用设置
Popen
,以减少文件描述符的泄漏。但是,我不熟悉
exec
子流程周围的机制和文件描述符的继承,所以前面提到的bug报告中的许多
Popen
文档和注释对我来说都不清楚。
听起来好像它会在执行子流程之前关闭我的流程中所有打开的文件描述符(包括活动的请求套接字、日志文件句柄等)。这听起来比泄漏套接字要好,但仍然会导致错误。
然而,在实践中,当我在web请求期间使用
close_fds=True
时,它似乎工作得很好,到目前为止,我还无法构建这样一个场景:它实际上关闭了任何其他请求套接字、数据库请求等。
文件说明:
如果close_fds为true,则在执行子进程之前,将关闭除0、1和2之外的所有文件描述符。
所以我的问题是:在多线程Python web服务器中将
close_fds=True
传递到
Popen
是“安全的”还是“正确的”?或者,如果其他请求同时执行文件/套接字IO,我是否应该期望这会产生副作用?

最佳答案:

subprocess32
import tempfile
import subprocess32 as subprocess

fp = open('test.txt', 'w')

fp.write("some stuff")

echoed = tempfile.TemporaryFile()
p = subprocess.Popen(("echo", "this", "stuff"), stdout=echoed, close_fds=True)
p.wait()
echoed.seek(0)

fp.write("whatevs")
fp.write(echoed.read())
fp.close()

我得到了预期的结果。
因此,似乎
subprocess
some stuffwhatevsecho this stuff
的含义并不意味着父进程中打开的文件(套接字等)在执行子进程后将不可用。
同样值得注意的是:
test.txt
默认值
close
在POSIX系统上,AFAICT。这对我意味着它不像听起来那么危险。