背景
代码应该获取一个文件对象并使用 awk 从中提取信息。
它使用 readlines() 和 'pieceSize' 作为参数。 “pieceSize”是我希望 readlines() 在遍历文件时使用的 MB 数。我这样做是希望如果需要读取的文件比我的计算机内存大得多,我的程序不会遇到麻烦。 正在读取的文件有很多行和列。
下面的代码尝试使用 awk 从第一行读取第一个字段。
import os
from subprocess import Popen, PIPE, STDOUT
def extract_info(file_object):
pieceSize = 16777216 # 16MB
for line in file_object.readlines(pieceSize):
eachline = line.rsplit() # removing extra returns
p = Popen(['awk','{{print `$`1}}'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
pOut = p.communicate(input=eachline)[0]
print(pOut.decode())
错误信息
我收到的错误内容类似于...
... in _communicate_with_poll(self, input)
chunk = input[input_offset : input_offset + _PIPE_BUF]
try:
-> input_offset += os.write(fd, chunk)
except OSError as e:
if e.errno == errno.EPIPE:
TypeError: must be string or buffer, not list
发生错误是因为
str.rsplit()
返回一个 list,但 Popen.communicate()
需要一个字符串(或缓冲区)。所以你不能将 eachline
的结果传递给 communicate()
。
这就是问题的原因,但我不确定你为什么要分开线路。
rsplit()
将在 all 空白上拆分,包括空格、制表符等。这真的是您想要的吗?
此外,此代码将迭代
readlines()
返回的第一组行。文件的其余部分仍未处理。您需要一个外部循环来保持运行,直到输入文件耗尽(可能在调用代码中您没有显示?)。然后每行输入都会调用 Popen
一次,这将是非常低效的。
我建议你完全用Python来处理。
line.split()[0]
有效地为您提供所需的数据(文件的第一列),而无需将其传递给 awk。逐行迭代可以节省内存。
也许发电机是更好的解决方案:
def extract_info(file_object):
for line in file_object:
yield line.split()[0]
然后你可以在调用代码中迭代它:
with open('inputfile') as f:
for first_field in extract_info(f):
print first_field
您需要将 split 返回的列表中的字符串传递给输入:
pOut, _ = p.communicate(input=eachline[0])
您正在传递
line.rsplit()
即一个列表,不确定您到底想传递什么,也许您想要 input=" ".join(eachline)
但无论它是什么,它应该是一个字符串,而不是您传递给输入的列表本身。另外你的 awk 语法似乎不正确。
您还可以迭代文件对象本身以逐行进行,完全避免读取行。
for line in file_object:
所以整个代码会是这样的:
def extract_info(file_object):
for line in file_object:
eachline = line.rsplit() # removing extra returns
p = Popen(['awk','{print $1}'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
pOut,_ = p.communicate(input=" ".join(eachline))
print(pOut.decode())
显然修复了
eachline
逻辑以执行您期望它执行的任何操作。
另一方面,根本不需要使用 awk,您可以使用 python 完成所有这些工作。
def extract_info(file_object):
for line in file_object:
eachline = line.split(None, 1)
print(eachline[0])
或者更简洁地使用 map 和 python3 的扩展可迭代解包:
def extract_info(file_object):
for i, *_ in map(str.split, file_object):
print(i)
尚不完全清楚您期望实现什么输出。
但是,也许这会有所帮助:
awk
,你可以使用Python来实现。readline
或 for line in file_handler
加载每一行,您应该避免使用 readlines()
和 read()
加载整个文件。试试这个:
with open('myfile.txt') as f:
for line in f:
first_word = line.split()[0]