【问题标题】:subprocess.call子进程调用
【发布时间】:2013-01-17 19:39:10
【问题描述】:

我是 subprocess.call 函数的新手,我尝试了同一调用的不同组合,但它不起作用。

我正在尝试执行以下命令:

cmd = 'sort -k1,1 -k4,4n -k5,5n '+outpath+fnametempout+' > '+outpath+fnameout
print cmd

如果我尝试调用,我会收到错误:

cmd = cmd.split(" ")
print cmd
subprocess.call(cmd)

我得到的错误是:

sort: stat failed: >: No such file or directory

【问题讨论】:

    标签: python subprocess


    【解决方案1】:

    这样做,您需要shell=True 才能允许shell 重定向工作。

    subprocess.call('sort -k1,1 -k4,4n -k5,5n '+outpath+fnametempout,shell=True)
    

    更好的方法是:

    with open(outpath+fnameout,'w') as fout: #context manager is OK since `call` blocks :)
        subprocess.call(cmd,stdout=fout)
    

    这避免了一起生成 shell 并且可以安全地免受 shell 注入类型的攻击。在这里,cmd 是您原来的列表,例如

    cmd = 'sort -k1,1 -k4,4n -k5,5n '+outpath+fnametempout
    cmd = cmd.split()
    

    还应该指出,python 有非常好的排序工具,所以我怀疑是否真的有必要通过子进程将工作交给sort


    最后,与其使用str.split 从字符串中拆分参数,不如使用shlex.split 更好,因为这样可以正确处理带引号的字符串。

    >>> import shlex
    >>> cmd = "foo -b -c 'arg in quotes'"
    >>> print cmd.split()
    ['foo', '-b', '-c', "'arg", 'in', "quotes'"]
    >>> print shlex.split(cmd)
    ['foo', '-b', '-c', 'arg in quotes']
    

    【讨论】:

    • +1。但是shlex 的方向有点不对。首先构建list 而不是str 始终是最好的选择。如果您不可避免地拥有str,并且您正在使用shell=True(或者您在Windows 上),只需传递str。如果您确实必须拆分字符串,那么是的,绝对使用shlex.split 而不是str.split。但这应该是你最后的手段,而不是你的第一个手段。在这种情况下,没有任何分裂的理由。
    • 另一个问题是shlex.split() 不能完美地模拟shell。 It may break in subtle ways。正如@abarnert 所说:显式构造列表而不是使用shlex.split()
    【解决方案2】:

    不要在python中执行以上命令:

    import subprocess
    import sys
    proc = subprocess.Popen(['sort','-k1','1', '-k4','4n', '-k5','5n',    '+outpath+fnametempout+', '>', '+outpath+fnameout'],stdin=subprocess.PIPE)
    proc.communicate()
    

    【讨论】:

      【解决方案3】:

      示例:

      subprocess.call(['ps','aux'])
      lines=subprocess.check_output(['ls','-al'])
      line_list = lines.split('\n')
      
      or
      
      handle = subprocess.Popen('ls',stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,close_fds=True)
      handle.stdout.read()
      

      【讨论】:

      • OPs 问题是存在> shell 重定向操作符,而subprocess 默认不使用shell。解决方案是使用@mgilson 演示的stdout=fout。不要使用out = handle.stdout.read(),如果你已经多次使用PIPE,请改用out ,err = handle.communicate(input)——否则子进程可能会死锁(虽然这里不太可能使用ls
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多