无法在python中调用子进程“ls -l folder | wc -l”

时间:2016-02-13 03:04:11

标签: python subprocess call

我想使用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

我该如何解决?

4 个答案:

答案 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())