我正在嘗試通過在下面的代碼中使用 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'"`
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())
現在嘗試更改為串列。
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`
uj5u.com熱心網友回復:
您的命令仍然是錯誤的。如果您只想像 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)
如果要洗掉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)
請特別注意引數 tosed和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))
可能你想把rstrip和replace放在里面if以避免不必要的作業。當然,可以對 shell 管道進行相同的重構。
uj5u.com熱心網友回復:
根據上面的戈登 - 默認情況下 Popen() 對待
sed 's/"/ /g'
作為要運行的命令的名稱,而不是命令名稱加一個引數。因此,您需要執行以下操作之一:
p2 = subprocess.Popen(['sed', 's/"/ /g'], stdin=p1.stdout, stdout=subprocess.PIPE)
或者
p2 = subprocess.Popen('sed \'s/"/ /g\'', stdin=p1.stdout, stdout=subprocess.PIPE, shell=True)
使用 shell=True 使 Popen 函式將字串拆分為包含命令和引數的串列。
另請注意, p0 是您的最后一個結果,但您呼叫 p01.communicate()
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/373057.html
