我正在使用Google云端存储客户端库。
我正在尝试使用以下代码打开并处理CSV文件(已经上传到存储桶):
filename = '/<my_bucket/data.csv'
with gcs.open(filename, 'r') as gcs_file:
csv_reader = csv.reader(gcs_file, delimiter=',', quotechar='"')
我得到错误&#34;参数1必须是迭代器&#34;响应csv.reader的第一个参数(即gcs_file)。显然gcs_file不支持迭代器.next方法。
有关如何进行的任何想法?我是否需要包装gcs_file并在其上创建迭代器或者是否有更简单的方法?
答案 0 :(得分:3)
我认为你拥有自己的为csv.reader设计的包装器/迭代器会更好。如果gcs_file支持Iterator协议,则不清楚next()应该返回什么以始终容纳其使用者。
根据csv reader doc,它
返回一个读取器对象,它将迭代给定csvfile中的行。 csvfile可以是任何支持迭代器协议的对象,每次调用next()方法时都返回一个字符串 - 文件对象和列表对象都是合适的。如果csvfile是一个文件对象,则必须在平台上打开“b”标志,这会产生影响。
它需要来自底层文件的一大块原始字节,不一定是一行。你可以有这样的包装(未经测试):
class CsvIterator(object)
def __init__(self, gcs_file, chunk_size):
self.gcs_file = gcs_file
self.chunk_size = chunk_size
def __iter__(self):
return self
def next(self):
result = self.gcs_file.read(size=self.chunk_size)
if not result:
raise StopIteration()
return result
关键是一次读取一个块,这样当你有一个大文件时,你不会爆炸内存或从urlfetch中经历超时。
甚至更简单。要使用内置的iter:
csv.reader(iter(gcs_file.readline, ''))
答案 1 :(得分:1)
试试这个:
from StringIO import StringIO
filename = '/<my_bucket/data.csv'
with gcs.open(filename, 'r') as gcs_file:
csv_reader = csv.reader(StringIO(gcs_file.read()), delimiter=',',
quotechar='"')
但这并不理想。我已经提交了一个功能请求,要求让GCS文件支持迭代。