Tec*_*eek 7 python shell subprocess
我试图通过在下面的代码中使用 subprocess 模块来使用 python 运行 shell 命令,但我不明白为什么我的脚本会抛出如下错误。有人可以帮助我我所缺少的吗?
Traceback (most recent call last):
File "/Scripts/test_file.py", line 6, in <module>
p2 = subprocess.Popen('sed s\'/"/ /g\'', stdin=p1.stdout, stdout=subprocess.PIPE)
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/subprocess.py", line 854, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/subprocess.py", line 1702, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: "sed s'/"/ /g'"`
Run Code Online (Sandbox Code Playgroud)
import subprocess
#output3.txt='/Users/boggulv/Desktop/output3.txt'
p1 = subprocess.Popen( ['cat', 'output3.txt'], stdout=subprocess.PIPE)
print(p1)
p2 = subprocess.Popen('sed s\'/"/ /g\'', stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen('grep "sO"', stdin=p2.stdout,stdout=subprocess.PIPE)
p4 = subprocess.Popen('grep -v "get"', stdin=p3.stdout, stdout=subprocess.PIPE)
p5 = subprocess.Popen('cut -d \',\' -f2', stdin=p4.stdout, stdout=subprocess.PIPE)
p6 = subprocess.Popen('sed \'s/"//g\'', stdin=p5.stdout, stdout=subprocess.PIPE)
p7 = subprocess.Popen('sort', stdin=p6.stdout, stdout=subprocess.PIPE)
p8 = subprocess.Popen('sort', stdin=p8.stdout, stdout=subprocess.PIPE)
p9 = subprocess.Popen('uniq -c', stdin=p8.stdout, stdout=subprocess.PIPE)
p0 = subprocess.Popen('sort -nr', stdin=p9.stdout, stdout=subprocess.PIPE)
print(p01.communicate())
Run Code Online (Sandbox Code Playgroud)
现在尝试更改为列表。
p2 = subprocess.Popen('sed \'s/"/ /g\'', stdin=p1.stdout, stdout=subprocess.PIPE, shell=True)
p3 = subprocess.Popen(['grep','"shipOption"'], stdin=p2.stdout,stdout=subprocess.PIPE,shell = True)
p4 = subprocess.Popen(['grep','-v', '"getShipMethod"'], stdin=p3.stdout, stdout=subprocess.PIPE,shell = True)
p5 = subprocess.Popen(['cut','-d','\',\'', '-f2'], stdin=p4.stdout, stdout=subprocess.PIPE,shell = True)
p6 = subprocess.Popen(['sed','\'s/"//g\''],stdin=p5.stdout, stdout=subprocess.PIPE,shell = True)
p7 = subprocess.Popen(['sort'], stdin=p6.stdout, stdout=subprocess.PIPE,shell = True)
p8 = subprocess.Popen(['uniq', '-c'], stdin=p7.stdout, stdout=subprocess.PIPE,shell = True)
p9 = subprocess.Popen(['sort', '-nr'], stdin=p8.stdout, stdout=subprocess.PIPE,shell = True)
p0 = subprocess.Popen(['head', '-10'], stdin=p9.stdout, stdout=subprocess.PIPE,shell = True)```
New Error:
`usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
usage: grep [-abcdDEFGHhIiJLlMmnOopqRSsUVvwXxZz] [-A num] [-B num] [-C[num]]
[-e pattern] [-f file] [--binary-files=value] [--color=when]
[--context[=num]] [--directories=action] [--label] [--line-buffered]
[--null] [pattern] [file ...]
usage: cut -b list [-n] [file ...]
cut -c list [file ...]
cut -f list [-s] [-w | -d delim] [file ...]
(b'', None)
cat: stdin: Input/output error`
Run Code Online (Sandbox Code Playgroud)
你的命令还是错误的。如果您只想像 shell 一样运行这些命令,那么最简单的方法就是……使用 shell。
result = subprocess.run('''
# useless cat, but bear with
cat output3.txt |
sed 's/"/ /g' |
grep "shipOption" |
grep -v "getShipMethod" |
cut -d ',' -f2 |
sed 's/"//g' |
sort |
uniq -c |
sort -nr |
head -10
''',
# Probably add these too
check=True,
capture_output=True,
# We are using the shell for piping etc
shell=True)
Run Code Online (Sandbox Code Playgroud)
如果您想删除shell=True并手动运行所有这些进程,您必须了解 shell 的工作原理。特别是,您需要修复引号,以便您运行的命令具有在shell 处理语法引号后保留的引号。
p1 = subprocess.Popen(['cat', 'output3.txt'], stdout=subprocess.PIPE) # still useless
p2 = subprocess.Popen(['sed','s/"/ /g'], stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(['grep', "shipOption"], stdin=p2.stdout,stdout=subprocess.PIPE)
p4 = subprocess.Popen(['grep', '-v', "getShipMethod"], stdin=p3.stdout, stdout=subprocess.PIPE)
p5 = subprocess.Popen(['cut', '-d', ',', '-f2'], stdin=p4.stdout, stdout=subprocess.PIPE)
p6 = subprocess.Popen(['sed', 's/"//g'],stdin=p5.stdout, stdout=subprocess.PIPE)
p7 = subprocess.Popen(['sort'], stdin=p6.stdout, stdout=subprocess.PIPE)
p8 = subprocess.Popen(['uniq', '-c'], stdin=p7.stdout, stdout=subprocess.PIPE)
p9 = subprocess.Popen(['sort', '-nr'], stdin=p8.stdout, stdout=subprocess.PIPE)
p0 = subprocess.Popen(['head', '-10'], stdin=p9.stdout, stdout=subprocess.PIPE)
Run Code Online (Sandbox Code Playgroud)
特别注意如何删除sed和grep的参数的外引号,以及我们如何删除shell=True所有地方。根据经验,如果Popen(或其他subprocess方法)的第一个参数是列表,则不应使用shell=True,反之亦然。(在某些情况下,您可以传递一个列表,shell=True但是......我们甚至不开始去那里。)
不过,所有这些看起来都毫无意义,因为 Python 可以很好地完成所有这些事情。
from collections import Counter
counts = Counter()
with open('output3.txt', 'r', encoding='utf-8') as lines:
for line in lines:
line = line.rstrip('\n').replace('"', ' ')
if "shipOption" in line and "getShipMethod" not in line:
field = line.split(',')[1].replace('"', '')
counts[field] += 1
print(counts.most_common(10))
Run Code Online (Sandbox Code Playgroud)
您可能希望将rstrip和replace放入其中if以避免不必要的工作。当然,可以对 shell 管道进行相同的重构。
| 归档时间: |
|
| 查看次数: |
9742 次 |
| 最近记录: |