4

Google Cloud Storage クライアント ライブラリを使用しています。

次のようなコードを使用して、(すでにバケットにアップロードされた) CSV ファイルを開いて処理しようとしています。

filename = '/<my_bucket/data.csv'
with gcs.open(filename, 'r') as gcs_file:
    csv_reader = csv.reader(gcs_file, delimiter=',', quotechar='"')

csv.reader (つまり、gcs_file) の最初の引数に応答して、「引数 1 は反復子でなければなりません」というエラーが表示されます。どうやら gcs_file は iterator .next メソッドをサポートしていないようです。

続行する方法についてのアイデアはありますか?gcs_file をラップしてイテレータを作成する必要がありますか、それとももっと簡単な方法がありますか?

4

2 に答える 2

3

csv.reader用に設計された独自のラッパー/イテレータを用意したほうがよいと思います。gcs_file がIteratorプロトコルをサポートしていた場合、コンシューマーに常に対応するために next() が何を返す必要があるかは明確ではありません。

csvリーダーのドキュメントによると、

指定された 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, ''))
于 2013-07-24T19:58:45.763 に答える
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 ファイルで反復処理をサポートする機能リクエストを提出しました。

于 2013-07-24T18:26:33.953 に答える