我有一个处理登录的 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 上运行(这解释了加载时间)
最佳答案
close_fds
对标准输出没有影响。您需要 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 命令。
此外,您可能还想加强 token 的安全性。 5 个字符可以被暴力破解,但更重要的是,random.choice
不是加密安全的。使用 random.SystemRandom().choice
相反,或者更现代的secrets.token_urlsafe
在 Python 3.6+ 中。
关于python - 为什么 subprocess.Popen 阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49310057/