Python子流程模块比命令慢得多(已弃用)
因此,我编写了一个脚本,在命令行上使用nc访问多个服务器,最初我使用Python的commands模块并调用commands.getoutput(),该脚本在大约45秒内运行。由于不推荐使用命令,我想将一切都改为使用子流程模块,但现在脚本需要2m45秒才能运行。有人知道为什么会这样吗 我以前的经历:Python子流程模块比命令慢得多(已弃用),python,performance,command,subprocess,Python,Performance,Command,Subprocess,因此,我编写了一个脚本,在命令行上使用nc访问多个服务器,最初我使用Python的commands模块并调用commands.getoutput(),该脚本在大约45秒内运行。由于不推荐使用命令,我想将一切都改为使用子流程模块,但现在脚本需要2m45秒才能运行。有人知道为什么会这样吗 我以前的经历: output = commands.getoutput("echo get file.ext | nc -w 1 server.com port_num") 现在我有 p = Popen('ech
output = commands.getoutput("echo get file.ext | nc -w 1 server.com port_num")
现在我有
p = Popen('echo get file.ext | nc -w 1 server.com port_num', shell=True, stdout=PIPE)
output = p.communicate()[0]
提前感谢您的帮助 我希望
子进程
比命令
慢。如果不想说明这是脚本运行缓慢的唯一原因,那么您应该看看源代码。只有不到100行,大部分工作都委托给了os
中的函数,其中许多函数直接从c posix库中获取(至少在posix系统中是这样)。请注意,命令
仅适用于unix,因此它不需要做任何额外的工作来确保跨平台兼容性
现在看一看。有1500多行代码,都是纯Python代码,执行各种检查以确保一致的跨平台行为。基于此,我希望子流程
的运行速度比命令
慢
>>> %timeit commands.getoutput('echo "foo" | cat')
100 loops, best of 3: 3.02 ms per loop
>>> %timeit subprocess.check_output('echo "foo" | cat', shell=True)
100 loops, best of 3: 5.76 ms per loop
我对这两个模块进行了计时,在一些非常基本的情况下,子流程
的速度几乎是命令
的两倍
>>> %timeit commands.getoutput('echo "foo" | cat')
100 loops, best of 3: 3.02 ms per loop
>>> %timeit subprocess.check_output('echo "foo" | cat', shell=True)
100 loops, best of 3: 5.76 ms per loop
建议一些有助于提高脚本性能的良好改进。但即使在应用它们之后,请注意子流程
仍然较慢
假设您在一行中多次执行上述命令,这将累积起来,并至少解释部分性能差异
无论如何,我将您的问题解释为关于
子流程
和命令
的相对性能,而不是关于如何加快脚本速度。对于后一个问题,瑞士的答案更好。这里似乎至少有两个不同的问题
首先,您不正确地使用了Popen。以下是我看到的问题:
from subprocess import PIPE
args = ['nc', '-w', '1', 'server.com', 'port_num']
p = subprocess.Popen(args, stdin=PIPE, stdout=PIPE)
output = p.communicate("get file.ext")
print output[0]
其次,您认为手动运行时结束速度快于贯穿子流程时结束速度的事实表明,这里的问题是您没有将正确的字符串传递给nc
。可能发生的情况是服务器正在等待终止字符串结束连接。如果您没有传递此消息,则连接可能会保持打开状态,直到超时
手动运行
nc
,找出终止字符串是什么,然后更新传递给communicate
的字符串。通过这些更改,它应该运行得更快。从shell运行命令需要多长时间?只要服务器没有超时,结果几乎是实时的0m0.274s用户0m0.071s sys 0m0.134sdo其他命令,如“ls”、“uname-a”等。使用子流程模块执行命令也需要很长时间?不,不是从我所看到的。同样,当我运行与上面相同的东西(在python解释器中)时,但随着时间的推移,子流程实际上要快一点。不知道为什么它会慢一点,一旦纳入我的代码…似乎问题不在于子流程模块那么…啊,谢谢!我很高兴我没有发疯。我使用的是python 2.6,所以我甚至没有使用check_输出的选项。我怀疑这实际上不是问题所在。@Swiss,我同意不使用shell会更好。我想我是假设user1436110这样做是出于必要,并相应地回答了这个问题。仔细观察,我发现情况可能并非如此。但即使在应用了您建议的改进之后,子流程
也会变慢。请参阅上面的新计时。@senderle:子进程可能较慢。但是,1或2毫秒的差异非常小,不能解释原始问题提到的2分钟以上的差异。@user1436110,只是澄清一下:您正在下载大文件吗?大约几号?您是否在脚本中多次调用Popen
?您在注释中提到的运行时是一次调用nc
的运行时还是多次调用的运行时?是否有理由选择2?为什么字符串版本被认为是低效的?嗨@mooncarter,我不是OP,但我相信2)的建议是因为你想避免使用Shell=True。因此,您需要将命令添加为列表,而不是字符串。