我想使用call subprocess
运行此命令ls -l folder | wc -l
我在Python文件中的代码在这里:
subprocess.call(["ls","-l","folder","|","wc","-l"])
我收到如下错误消息:
ls: cannot access |: No such file or directory
ls: cannot access wc: No such file or directory
这就像调用子进程无法读取命令|wc
。
我该如何解决?
答案 0 :(得分:2)
使用字符串作为第一个参数试用shell选项:
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
....
<appSettings>
....
<add key="elmah.mvc.disableHandler" value="false" />
<add key="elmah.mvc.disableHandleErrorFilter" value="false" />
<add key="elmah.mvc.requiresAuthentication" value="false" />
<add key="elmah.mvc.IgnoreDefaultRoute" value="false" />
<add key="elmah.mvc.allowedRoles" value="*" />
<add key="elmah.mvc.allowedUsers" value="*" />
<add key="elmah.mvc.route" value="elmah" />
<add key="elmah.mvc.UserAuthCaseSensitive" value="true" />
<add key="AppName" value="ContactDatabase" />
</appSettings>
....
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
....
<modules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
....
<elmah>
<security allowRemoteAccess="yes"/>
<errorLog type="Elmah.XmlFileErrorLog, Elmah" size="500" logPath="~/App_Data" />
</elmah>
虽然这项工作有用,但请注意,建议不要使用subprocess.call("ls -l folder | wc -l",shell=True)
,因为它可能会通过shell injection引入安全问题。
答案 1 :(得分:1)
您可以通过将一个进程的stdout
与另一个进程stdin
连接来设置命令管道。在您的示例中,错误和最终输出将写入屏幕,因此我没有尝试重定向它们。这通常比communicate
更受欢迎,因为它不是等待一个程序在启动另一个程序之前完成(并且需要将数据移动到父程序中),它们并行运行。
import subprocess
p1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["wc","-l"], stdin=p1.stdout)
# close pipe in parent, its still open in children
p1.stdout.close()
p2.wait()
p1.wait()
答案 2 :(得分:0)
您需要自己实施管道逻辑才能使其正常工作。
def piped_call(prog1, prog2):
out, err = subprocess.call(prog1).communicate()
if err:
print(err)
return None
else:
return subprocess.call(prog2).communicate(out)
答案 3 :(得分:0)
您可以尝试使用subprocess.PIPE,假设您想避免使用subprocess.call(..., shell=True)
。
import subprocess
# Run 'ls', sending output to a PIPE (shell equiv.: ls -l | ... )
ls = subprocess.Popen('ls -l folder'.split(),
stdout=subprocess.PIPE)
# Read output from 'ls' as input to 'wc' (shell equiv.: ... | wc -l)
wc = subprocess.Popen('wc -l'.split(),
stdin=ls.stdout,
stdout=subprocess.PIPE)
# Trap stdout and stderr from 'wc'
out, err = wc.communicate()
if err:
print(err.strip())
if out:
print(out.strip())
对于Python 3,请记住这里使用的communicate()
方法将返回byte
对象而不是字符串。 :
在这种情况下,您需要使用decode()
将输出转换为字符串:
if err:
print(err.strip().decode())
if out:
print(out.strip().decode())