Python子进程模块比命令慢得多(已弃用)

2024-04-25 09:41:13 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我写了一个脚本,在命令行上使用nc访问一堆服务器,最初我使用的是Python的command s模块,调用commands.getoutput(),脚本运行了大约45秒。由于不推荐使用命令,我想将所有内容都改为使用子流程模块,但现在脚本需要2 m45s才能运行。有人知道为什么会这样吗?

我以前拥有的:

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]

提前谢谢你的帮助!


Tags: 模块命令行echo脚本comoutputgetserver
2条回答

我希望subprocesscommand慢。如果不想暗示这是脚本运行缓慢的原因,您应该看看^{}源代码。只有不到100行代码,而且大部分工作都委托给os中的函数,其中许多是直接从c posix库(至少在posix系统中)获取的。请注意,commands仅限于unix,因此它不需要做任何额外的工作来确保跨平台兼容性。

现在看看^{}。有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

Swiss建议一些有助于脚本性能的良好改进。但即使在应用了它们之后,也要注意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的相对性能,而不是如何加快脚本的速度。对于后一个问题,瑞士的回答更好。

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

首先,你不恰当地使用了教皇。以下是我看到的问题:

  1. 用一个Popen生成多个进程。
  2. 将一个字符串作为参数传入,而不是拆分参数。
  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的字符串。有了这些变化,它应该运行得更快。

相关问题 更多 >

    热门问题