蟒子模块比命令慢得多(不推荐)(Python subprocess module much slow

2019-06-25 04:59发布

所以我写访问了一堆使用命令行NC服务器的脚本,本来我是用Python的命令,模块和调用commands.getoutput()和脚本在约45秒就跑。 由于命令已过时,我想通过改变一切使用子模块,但现在的脚本需要2m45s运行。 任何人都有的,为什么这会是一个想法?

我收到:

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]

在此先感谢您的帮助!

Answer 1:

我希望subprocess比慢command 。 我无意暗示,这是你的脚本运行速度慢的唯一原因,你应该看看commands的源代码。 有少于100线,并且大部分的工作是从委托给功能os ,其中有许多是直采取从C POSIX库(至少在POSIX系统)。 请注意, commands是UNIX的而已,所以它没有做任何额外的工作来保证跨平台兼容性。

现在来看看subprocess 。 有超过1500线,全部纯Python,做各种检查,以确保一致的跨平台行为。 在此基础上,我希望subprocess来运行慢commands

我计时了两个模块,并在很基本的东西, subprocess几乎是两倍慢commands

>>> %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

瑞士提出了一些很好的改善,这将有助于你的脚本的性能。 但是,即使应用它们后,请注意, subprocess 较慢。

>>> %timeit commands.getoutput('echo "foo" | cat')
100 loops, best of 3: 2.97 ms per loop
>>> %timeit Popen('cat', stdin=PIPE, stdout=PIPE).communicate('foo')[0]
100 loops, best of 3: 4.15 ms per loop

假设你在一排执行上面的命令很多次,这将增加了,占了至少一些性能差异。

在任何情况下,我解释你的问题作为有关的相对性能subprocesscommand ,而不是关于如何加快你的脚本。 对于后一个问题,瑞士的回答是好。



Answer 2:

似乎有至少两个不同的问题在这里。

首先,你不恰当地使用POPEN。 下面是我看到的问题:

  1. 产卵多个进程与一个POPEN。
  2. 在传递一个字符串作为参数的个数,而不是分裂ARGS。
  3. 使用shell通过文本来处理,而不是内建的沟通方法。
  4. 使用shell而不是直接产卵过程。

这里是你的代码的修正版

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 。 这些变化应该运行得更快。



文章来源: Python subprocess module much slower than commands (deprecated)