Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python子流程模块比命令慢得多(已弃用)_Python_Performance_Command_Subprocess - Fatal编程技术网

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

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

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

我以前的经历:

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。以下是我看到的问题:

  • 使用一个Popen生成多个进程
  • 将一个字符串作为参数传入,而不是拆分参数
  • 使用shell将文本传递给进程,而不是内置的通信方法
  • 使用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
    的字符串。通过这些更改,它应该运行得更快。

    从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。因此,您需要将命令添加为列表,而不是字符串。