CONTEXT
代码应该使用awk获取文件对象并从中提取信息。
它使用带有'pieceSize'的readlines()作为参数。 '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
答案 0 :(得分:1)
发生错误是因为str.rsplit()
返回列表,但Popen.communicate()
需要字符串(或缓冲区)。因此,您无法将eachline
的结果传递给communicate()
。
这就是问题的原因,但我不确定你为什么要拆分线路。 rsplit()
将拆分所有空白,包括空格,制表符等。这真的是你想要的吗?
此外,此代码将迭代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
答案 1 :(得分:0)
您需要将从split返回的列表中的字符串传递给input:
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])
或者更简洁地使用python3的map和扩展的可迭代解包:
def extract_info(file_object):
for i, *_ in map(str.split, file_object):
print(i)
答案 2 :(得分:0)
目前还不完全清楚您期望实现的输出。
但是,这可能会有所帮助:
awk
如果你所做的只是打印一行中的第一个单词,你可以使用python。readline
或for line in file_handler
加载每一行,则应避免使用readlines()
和{{1}加载整个文件。试试这个:
read()