将子进程的输出转换为 csv.reader 对象
Converting output from subprocess to csv.reader object
有没有办法从子进程中获取输出并将其转换为可迭代的 csv.reader 或 csv.DictReader 对象?这是我一直在尝试的代码:
p2 = subprocess.Popen("sort command...", stdout=subprocess.PIPE)
output = p2.communicate()[0]
edits = csv.reader(output, delimiter="\t")
基本上,我正在对一个大型 CSV 文件进行排序,然后我想将其作为 csv.reader 对象放入 Python。
我得到的错误是
Error: iterator should return strings, not int (did you open the file in text mode?)
有没有办法把这个字节流当作一个 csv.reader 对象,或者我是不是想错了?
这是Python中的一个问题 3. CSV模块需要unicode输入,而不是字节串。除此之外,csv.reader()
需要一个可迭代对象,例如一个打开的文件或一个字符串列表。试试这个:
encoding = 'ascii' # specify the encoding of the CSV data
p2 = subprocess.Popen(['sort', '/tmp/data.csv'], stdout=subprocess.PIPE)
output = p2.communicate()[0].decode(encoding)
edits = csv.reader(output.splitlines(), delimiter=",")
for row in edits:
print(row)
如果 /tmp/data.csv
包含(我使用逗号作为分隔符):
1,2,3,4
9,10,11,12
a,b,c,d
5,6,7,8
那么输出将是:
['1', '2', '3', '4']
['5', '6', '7', '8']
['9', '10', '11', '12']
['a', 'b', 'c', 'd']
以下对我有用(尽管文档警告阅读 stdout
)。用 io.TextIOWrapper()
包装 stdout
支持在字段数据中嵌入换行符。
这样做允许使用生成器,其优点是允许 stdout
增量读取,一次读取一行。
p2 = subprocess.Popen(["sort", "tabbed.csv"], stdout=subprocess.PIPE)
output = io.TextIOWrapper(p2.stdout, newline=os.linesep)
edits = csv.reader((line for line in output), delimiter="\t")
for row in edits:
print(row)
输出:
['1', '2', '3', '4']
['5', '6', '7', '8']
['9', '10', '11', '12']
['a', 'b\r\nx', 'c', 'd']
tabbed.csv
输入测试文件包含以下内容(其中 »
代表制表符,≡
代表换行符):
1»2»3»4
9»10»11»12
a»"b≡x"»c»d
5»6»7»8
要启用文本模式,传递universal_newlines=True
参数:
#!/usr/bin/env python3
import csv
from subprocess import Popen, PIPE
with Popen(["sort", "a.csv"], stdout=PIPE, universal_newlines=True) as p:
print(list(csv.reader(p.stdout, delimiter="\t")))
如果您需要解释嵌入在引号字段中的换行符,则创建 io.TextIOWrapper
,以传递 newline=''
参数:
#!/usr/bin/env python3
import csv
import io
from subprocess import Popen, PIPE
with Popen(["sort", "a.csv"], stdout=PIPE) as p, \
io.TextIOWrapper(p.stdout, newline='') as text_file:
print(list(csv.reader(text_file, delimiter="\t")))
此外,TextIOWrapper
允许明确指定字符编码(否则使用默认 locale.getpreferredencoding(False)
)。
注意:您不需要外部 sort
命令。您可以按纯 Python:
对行进行排序
#!/usr/bin/env python3
import csv
with open('a.csv', newline='') as text_file:
rows = list(csv.reader(text_file, delimiter="\t"))
rows.sort()
print(rows)
注意:更高版本对 csv 行而不是物理行进行排序(如果需要,您可以对行进行排序)。
如果您的 CSV 文件有列标题,此方法有效。
[ user@system currentDir ]$ ./ProgramThatCreatesCSVData
first,second,third,fourth
1,2,3,4
9,10,11,12
a,b,c,d
5,6,7,8
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$ cat CSVtoDict.py
#!/usr/bin/python3
"""Sample program to open a pipe to run a command.
That command generates a CSV with heading names in the first row.
Output of this program is a conversion of that CSV to a list of dictionaries,
in pprint format."""
import csv, pprint, subprocess, io
pipe = subprocess.Popen(["./ProgramThatCreatesCSVData"], stdout=subprocess.PIPE)
pipeWrapper = io.TextIOWrapper(pipe.stdout)
pipeReader = csv.DictReader(pipeWrapper)
listOfDicts = [ dict(row) for row in pipeReader ]
pprint.pprint(listOfDicts)
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$ python3 CSVtoDict.py
[{'first': '1', 'fourth': '4', 'second': '2', 'third': '3'},
{'first': '9', 'fourth': '12', 'second': '10', 'third': '11'},
{'first': 'a', 'fourth': 'd', 'second': 'b', 'third': 'c'},
{'first': '5', 'fourth': '8', 'second': '6', 'third': '7'}]
[ user@system currentDir ]$
有没有办法从子进程中获取输出并将其转换为可迭代的 csv.reader 或 csv.DictReader 对象?这是我一直在尝试的代码:
p2 = subprocess.Popen("sort command...", stdout=subprocess.PIPE)
output = p2.communicate()[0]
edits = csv.reader(output, delimiter="\t")
基本上,我正在对一个大型 CSV 文件进行排序,然后我想将其作为 csv.reader 对象放入 Python。
我得到的错误是
Error: iterator should return strings, not int (did you open the file in text mode?)
有没有办法把这个字节流当作一个 csv.reader 对象,或者我是不是想错了?
这是Python中的一个问题 3. CSV模块需要unicode输入,而不是字节串。除此之外,csv.reader()
需要一个可迭代对象,例如一个打开的文件或一个字符串列表。试试这个:
encoding = 'ascii' # specify the encoding of the CSV data
p2 = subprocess.Popen(['sort', '/tmp/data.csv'], stdout=subprocess.PIPE)
output = p2.communicate()[0].decode(encoding)
edits = csv.reader(output.splitlines(), delimiter=",")
for row in edits:
print(row)
如果 /tmp/data.csv
包含(我使用逗号作为分隔符):
1,2,3,4 9,10,11,12 a,b,c,d 5,6,7,8
那么输出将是:
['1', '2', '3', '4'] ['5', '6', '7', '8'] ['9', '10', '11', '12'] ['a', 'b', 'c', 'd']
以下对我有用(尽管文档警告阅读 stdout
)。用 io.TextIOWrapper()
包装 stdout
支持在字段数据中嵌入换行符。
这样做允许使用生成器,其优点是允许 stdout
增量读取,一次读取一行。
p2 = subprocess.Popen(["sort", "tabbed.csv"], stdout=subprocess.PIPE)
output = io.TextIOWrapper(p2.stdout, newline=os.linesep)
edits = csv.reader((line for line in output), delimiter="\t")
for row in edits:
print(row)
输出:
['1', '2', '3', '4']
['5', '6', '7', '8']
['9', '10', '11', '12']
['a', 'b\r\nx', 'c', 'd']
tabbed.csv
输入测试文件包含以下内容(其中 »
代表制表符,≡
代表换行符):
1»2»3»4
9»10»11»12
a»"b≡x"»c»d
5»6»7»8
要启用文本模式,传递universal_newlines=True
参数:
#!/usr/bin/env python3
import csv
from subprocess import Popen, PIPE
with Popen(["sort", "a.csv"], stdout=PIPE, universal_newlines=True) as p:
print(list(csv.reader(p.stdout, delimiter="\t")))
如果您需要解释嵌入在引号字段中的换行符,则创建 io.TextIOWrapper
,以传递 newline=''
参数:
#!/usr/bin/env python3
import csv
import io
from subprocess import Popen, PIPE
with Popen(["sort", "a.csv"], stdout=PIPE) as p, \
io.TextIOWrapper(p.stdout, newline='') as text_file:
print(list(csv.reader(text_file, delimiter="\t")))
此外,TextIOWrapper
允许明确指定字符编码(否则使用默认 locale.getpreferredencoding(False)
)。
注意:您不需要外部 sort
命令。您可以按纯 Python:
#!/usr/bin/env python3
import csv
with open('a.csv', newline='') as text_file:
rows = list(csv.reader(text_file, delimiter="\t"))
rows.sort()
print(rows)
注意:更高版本对 csv 行而不是物理行进行排序(如果需要,您可以对行进行排序)。
如果您的 CSV 文件有列标题,此方法有效。
[ user@system currentDir ]$ ./ProgramThatCreatesCSVData
first,second,third,fourth
1,2,3,4
9,10,11,12
a,b,c,d
5,6,7,8
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$ cat CSVtoDict.py
#!/usr/bin/python3
"""Sample program to open a pipe to run a command.
That command generates a CSV with heading names in the first row.
Output of this program is a conversion of that CSV to a list of dictionaries,
in pprint format."""
import csv, pprint, subprocess, io
pipe = subprocess.Popen(["./ProgramThatCreatesCSVData"], stdout=subprocess.PIPE)
pipeWrapper = io.TextIOWrapper(pipe.stdout)
pipeReader = csv.DictReader(pipeWrapper)
listOfDicts = [ dict(row) for row in pipeReader ]
pprint.pprint(listOfDicts)
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$
[ user@system currentDir ]$ python3 CSVtoDict.py
[{'first': '1', 'fourth': '4', 'second': '2', 'third': '3'},
{'first': '9', 'fourth': '12', 'second': '10', 'third': '11'},
{'first': 'a', 'fourth': 'd', 'second': 'b', 'third': 'c'},
{'first': '5', 'fourth': '8', 'second': '6', 'third': '7'}]
[ user@system currentDir ]$