为什么subprocess.Popen阻塞?

时间:2018-03-15 22:09:41

标签: python subprocess

我有一个处理登录的python cgi脚本,这是因为我的网站是三个(学校)网站的组合,在我的网站可以使用之前,需要从这些网站中提取数据。这个提取需要2分钟,所以我想制作一个花哨的(半假的)加载屏幕。

我的注册码以:

结尾
import subprocess
token = "".join(random.choice(
                    string.ascii_lowercase + string.digits + string.ascii_uppercase)
                        for _ in range(5)) #generate 5 random characters
#run initScript
subprocess.Popen("python {}/python/initUser.py {} {}".format(
    os.getcwd(), uid,token), shell=True, stdin=None, stdout=None, stderr=None,
    close_fds=True)

print "Content-type: text/html"
print "Location: registerLoading.php?token={}".format(token)
print
sys.exit(0)

子进程线被盗:Run Process and Don't Wait

但是子进程线仍在阻塞,我无法弄清楚原因。

我正在开发ubuntu 16.04,它将在raspbarry pi 3上运行(这解释了加载时间)

1 个答案:

答案 0 :(得分:8)

close_fds对stdout没有影响。您需要devnull文件句柄(Python 3.3+中的subprocess.DEVNULL),以便通过调用exit关闭此脚本的标准输出:

subprocess.Popen(
   ["python", "python/initUser.py", uid, token],
   stdin=None, stdout=open(os.devnull, 'wb'), stderr=open(os.devnull, 'wb'))

请注意,我还用列表表单替换了shell命令。这使得代码对command injection安全 - 以前,每个用户都可以在您的网络服务器上运行任意shell命令。

此外,您可能还想加强令牌的安全性。 5个字符可以强制使用,但更重要的是,random.choice不具有加密安全性。请改用random.SystemRandom().choice,或使用Python 3.6 +中更现代的secrets.token_urlsafe