我一直在使用 subprocess.check_output()有一段时间从子进程捕获输出,但在某些情况下遇到了一些性能问题。我在 RHEL6 机器上运行它。
调用 Python 环境是 linux 编译的 64 位。我正在执行的子进程是一个 shell 脚本,它最终通过 Wine 触发一个 Windows python.exe 进程(为什么需要这种愚蠢是另一回事)。作为 shell 脚本的输入,我正在输入一小段 Python 代码,这些代码会传递给 python.exe。
当系统处于中等/高负载(40% 到 70% 的 CPU 利用率)时,我注意到使用 subprocess.check_output(cmd, shell=True)在 check_output 命令返回之前子进程完成执行后,可能会导致显着延迟(最多约 45 秒)。查看 ps -efH 的输出在此期间将调用的子进程显示为 sh <defunct> ,直到它最终以正常的零退出状态返回。
相反,使用 subprocess.call(cmd, shell=True)在相同的中/重负载下运行相同的命令将导致子进程立即返回,没有延迟,所有输出都打印到 STDOUT/STDERR(而不是从函数调用返回)。
为什么只有在 check_output() 时才会出现如此明显的延迟?正在将 STDOUT/STDERR 输出重定向到它的返回值,而不是当 call()只需将其打印回父级的 STDOUT/STDERR?
最佳答案
阅读文档,subprocess.call 和 subprocess.check_output 都是 subprocess.Popen 的用例。一个小的区别是,如果子进程返回非零退出状态,check_output 将引发 Python 错误。关于 check_output 的部分强调了更大的区别(我的重点):
The full function signature is largely the same as that of the Popen constructor, except that stdout is not permitted as it is used internally. All other supplied arguments are passed directly through to the Popen constructor.
那么 stdout 如何“在内部使用”?让我们比较一下 call 和 check_output:
def call(*popenargs, **kwargs):
return Popen(*popenargs, **kwargs).wait()
def check_output(*popenargs, **kwargs):
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
process = Popen(stdout=PIPE, *popenargs, **kwargs)
output, unused_err = process.communicate()
retcode = process.poll()
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
raise CalledProcessError(retcode, cmd, output=output)
return output
现在我们还要看看 Popen.communicate。这样做,我们注意到对于一个管道,communicate 做了几件事情,这些事情比简单地返回 Popen().wait() 花费更多的时间,如 call 可以。
一方面,无论您是否设置 shell=True,communicate 都会处理 stdout=PIPE。显然,call 没有。它只是让你的 shell 喷出任何东西......使其成为安全风险,as Python describes here .
其次,在 check_output(cmd, shell=True) 的情况下(只有一个管道)...您的子进程发送到 stdout 的任何内容都由 _communicate 方法中的 em>thread。并且 Popen 必须在额外等待子进程本身终止之前加入线程(等待它)!
另外,更简单的是,它将 stdout 处理为一个 list,然后必须将其连接成一个字符串。
简而言之,即使使用最少的参数,check_output 在 Python 进程中花费的时间也比 call 多得多。
关于python - subprocess.check_output 与 subprocess.call 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25333537/
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
“输出”是一个序列化的OpenStruct。定义标题try(:output).try(:data).try(:title)结束什么会更好?:) 最佳答案 或者只是这样:deftitleoutput.data.titlerescuenilend 关于ruby-on-rails-更好的替代方法try(:output).try(:data).try(:name)?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决