【问题标题】:convert from bash shell to python3 using subprocess.Popen()使用 subprocess.Popen() 从 bash shell 转换为 python3
【发布时间】:2016-10-02 22:48:10
【问题描述】:

我正在努力从 bash shell 转换为 python3。

这是我要转换为 python 的 shell 命令:

cat $outDir/aDir/* | cut -f2 | sort -u > $outDir/outFile.txt

我已经使用了subprocess.call(),它可以工作,但我想知道如何使用 Popen() 来实现。

这是我的代码不起作用:

import subprocess
import glob

filePath = outDir + 'aDir/*'
outFilePath = outDir + '/outFile.txt'

fileList = []
for files in glob.glob(filePath):
    fileList.append(files)
with open(files, 'r') as inFile, open(outFilePath, 'w') as outFile : 
  p = subprocess.Popen(['cat'], stdin=inFile, stdout=subprocess.PIPE)   
  p2 = subprocess.Popen(['cut', '-f2'], stdin = p1.stdout, stdout=subprocess.PIPE)
  p3 = subprocess.Popen(['sort', '-u'], stdin = p2.stdout, stdout = outFile)

你能解释一下为什么shell=True 是有害的吗?我在很多答案中看到它,但不知道为什么......

谢谢。

【问题讨论】:

  • stackoverflow.com/questions/3172470/… 解释了为什么要避免使用shell=True
  • @tripleee: 和 @tripleee: 和 this shows that shell=True can be useful(如果没有不受信任的输入,那么在直接使用 subprocess.Popen 重新实现 shell 管道时出错的可能性更大,而不是由于不兼容而导致错误对于一个简单的 shell 命令)。
  • 问题不在于它没用,而在于使用它需要理解。不幸的是,Shell 拥有的用户甚至比 PHP 和 VBscript 的总和还要多,他们甚至不知道绝对的基础知识。 (这个问题在这方面明显高于平均水平。)

标签: python bash shell subprocess popen


【解决方案1】:

只使用shell=True 并保留管道怎么样?

with open(files, 'r') as inFile, open(outFilePath, 'w') as outFile : 
  p = subprocess.Popen('cut -f2 | sort -u', shell=True, stdin=filePath, stdout=subprocess.PIPE)
  p.communicate()

或者更简单地说:

p = subprocess.Popen("cat {} | cut -f2 | sort -u > '{}'".format(filePath, outFilePath), shell=True)
p.communicate()

或者,甚至更多(感谢@tripleee!):

subprocess.call("cat {} | cut -f2 | sort -u > '{}'".format(filePath, outFilePath), shell=True)

至于shell=True,唯一的危险是如果您的输入不安全。我建议用单引号引用所有输入,并对所有输入进行转义和清理。

【讨论】:

  • 如果in 包含时髦的东西,您需要执行额外的步骤来将其从shell 解释中转义。
  • 如果files 是一个列表,open(files, 'r') 只会抛出一个错误。
  • 一旦你解决了这些问题,subprocess.Popen 就是不方便;请改用subprocess.call
  • 对不起,in 在 OP 的示例中应该是 filePath。还添加了call(),很好,谢谢!
【解决方案2】:

您需要将文件列表传递给cat 所以

subprocess.Popen(['cat'], stdin=inFile, stdout=subprocess.PIPE)

应该变成

subprocess.Popen(['cat'] + [fileList], stdout=subprocess.PIPE)

因此应该不再需要inFile

总之

import subprocess
import glob

filePath = outDir + '/aDir/*'
outFilePath = outDir + '/outFile.txt'

fileList = glob.glob(filePath)
with open(outFilePath, 'w') as outFile: 
  subprocess.Popen(['cat'] + [fileList], stdout=subprocess.PIPE)
  p2 = subprocess.Popen(['cut', '-f2'], stdin = p1.stdout, stdout=subprocess.PIPE)
  p3 = subprocess.Popen(['sort', '-u'], stdin = p2.stdout, stdout = outFile)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    相关资源
    最近更新 更多