subprocess.Popen实例化时,运行程序。但是,它不会等待-它会在后台将其触发,就像您
cmd&在shell中键入一样。因此,在上面的代码中,您实质上已经定义了竞争条件-
如果插入可以及时完成,它将看起来很正常,但是如果没有,则会得到意外的输出。您无需等待第一个
run()PID完成,您只需返回其
Popen实例并继续即可。
我不确定这种行为如何与文档相矛盾,因为Popen上有一些非常清晰的方法似乎表明它没有等待,例如:
Popen.wait() Wait for child process to terminate. Set and return returnpre attribute.
但是,我确实同意可以改进此模块的文档。
为了等待程序完成,我建议使用
subprocess的便捷方法
subprocess.call或
communicate在
Popen对象上使用(对于需要stdout的情况)。您已经在进行第二次通话了。
### START MAIN# copy some rows from a source table to a destination table# note that the destination table is empty when this script is runcmd = 'mysql -u ve --skip-column-names --batch --execute="insert into destination (select * from source limit 100000)" test'subprocess.call(cmd)# check to see how many rows exist in the destination tablecmd = 'mysql -u ve --skip-column-names --batch --execute="select count(*) from destination" test'process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)try: count = (int(process.communicate()[0][:-1]))except: count = 0
此外,在大多数情况下,您不需要在Shell中运行命令。这是其中一种情况,但是您必须像序列一样重写命令。这样一来,您还可以避免传统的外壳注入,而不必担心引用问题,例如:
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']subprocess.call(prog)
这甚至可以正常工作,并且不会像您期望的那样注入:
prog = ["printf", "%s", "<", "/etc/passwd"]subprocess.call(prog)
交互式尝试。您避免了注入外壳的可能性,尤其是在接受用户输入的情况下。我怀疑您正在使用与子进程通信的不太出色的字符串方法,因为您遇到使序列正常工作的麻烦:^)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)