我有一个命令行工具(实际上是几个),我正在用Python编写包装器。
该工具通常是这样使用的:
$ path_to_tool -option1 -option2 > file_out
from subprocess import call
call(['path_to_tool','-option1','option2'], stdout = file_out, stderr = log_file)
最佳答案
您可以使用subprocess做到这一点,但这并不简单。如果您查看文档中的Frequently Used Arguments,您会看到可以将PIPE作为stderr参数传递,该参数创建一个新管道,将该管道的一侧传递给子进程,并使另一侧可用作stderr属性。*
因此,您将需要维护该管道,并写入屏幕和文件。通常,正确地获取详细信息非常棘手。**在您的情况下,只有一个管道,并且您打算同步维护它,所以还不错。
import subprocess
proc = subprocess.Popen(['path_to_tool', '-option1', 'option2'],
stdout=file_out, stderr=subprocess.PIPE)
for line in proc.stderr:
sys.stdout.write(line)
log_file.write(line)
proc.wait()
for line in proc.stderr:会出现一些问题-基本上,如果您正在阅读的内容由于某种原因而没有被行缓冲,即使实际上有一半的数据需要处理,您也可以坐在那里等待换行您可以使用read(128)甚至read(1)一次读取块,以在需要时更平稳地获取数据。如果您需要在到达每个字节后立即获取每个字节,而又负担不起read(1)的费用,则需要将管道置于非阻塞模式并异步读取。)tee命令为您完成操作可能会更简单。subprocess.call('path_to_tool -option1 option2 2|tee log_file 1>2', shell=True,
stdout=file_out)
tool = subprocess.Popen(['path_to_tool', '-option1', 'option2'],
stdout=file_out, stderr=subprocess.PIPE)
tee = subprocess.Popen(['tee', 'log_file'], stdin=tool.stderr)
tool.stderr.close()
tee.communicate()
sh,shell,shell_command,shellout,iterpipes,sarge,cmd_utils,commandwrapper等。搜索“shell”,“subprocess”, “进程”,“命令行”等,然后找到您喜欢的解决方案,从而使问题变得微不足道。Popen参数:tool = subprocess.Popen(['path_to_tool', '-option1', 'option2'],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
tool.stderr的地方,改用tool.stdout,例如,对于最后一个示例:tee = subprocess.Popen(['tee', 'log_file'], stdin=tool.stdout)
tool.stdout.close()
tee.communicate()
tool.stdout.read(),并且新数据来自tool.stderr。如果数据太多,则可能导致管道溢出和子进程阻塞。但是,即使那没有发生,您也显然无法读取和记录stderr数据,除非有stdout发出一些信息。tee解决方案,则可以避免最初的问题...但是只能通过创建一个同样糟糕的新项目来解决。您有两个tee实例,而当您在一个实例上调用communicate时,另一个实例就坐在那里永远等待。select react 堆,gevent之类的东西来执行此操作。proc = subprocess.Popen(['path_to_tool', '-option1', 'option2'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def tee_pipe(pipe, f1, f2):
for line in pipe:
f1.write(line)
f2.write(line)
t1 = threading.Thread(target=tee_pipe, args=(proc.stdout, file_out, sys.stdout))
t2 = threading.Thread(target=tee_pipe, args=(proc.stderr, log_file, sys.stderr))
t3 = threading.Thread(proc.wait)
t1.start(); t2.start(); t3.start()
t1.join(); t2.join(); t3.join()
subprocess.communicate 函数正确获取了所有复杂的细节。但是您可能会发现,使用一种可以在PyPI和ActiveState上找到的异步子流程包装器实现甚至是来自像Twisted之类的成熟的异步框架中的子流程东西,要简单得多。subprocess Module部分中的示例展示了它们的用法,并且非常简单。select或poll react 器,但是要使该跨平台变得异常困难。)模块的The source,尤其是communicate及其助手,显示了如何执行此操作。 (我链接到3.3,因为在较早的版本中,communicate本身会犯一些重要的错误……)因此,如果需要多个管道,则尽可能使用communicate。就您而言,您不能使用communicate,但是幸运的是,您不需要多个管道。
关于python - Python:subprocess.call,stdout到文件,stderr到文件,在屏幕上实时显示stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18344932/
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
关闭。这个问题是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
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我怎样才能完成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)
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta