pythonでCloud Storageのファイル数を数えようとしたらこんなエラーがでました。
なんなんだと。
File "/........./lib64/python3.6/site-packages/google/api_core/page_iterator.py", line 227, in __iter__ raise ValueError("Iterator has already started", self) ValueError: ('Iterator has already started', <google.api_core.page_iterator.HTTPIterator object at 0x7fc844c4aeb8>)
そもそものコードはこちらです。
やりたいことは
- 対象フォルダのファイルを探す。
- ファイルが無ければ終了。
- ファイルがあればファイル名を表示する。
というものです。
from google.cloud import storage import sys storage_client = storage.Client() bucket = storage_client.bucket(BUCKET_NAME) ### 集計対象のファイルを探す blobs = bucket.list_blobs( prefix=TARGET_GCS_FOLDER + '/hoge_' ) if len(list(blobs)) == 0: print("Error, No target files....") sys.exit(1) for item in blobs: # <--- ここ!!! print(item.name)
そんでどうやらエラーの箇所はblobオブジェクトをイテレートしてファイル名を表示するところでした。
なぜかと?
どうやらblobオブジェクトのイテレーターは1回しか使えないみたいです。
File "/........./lib64/python3.6/site-packages/google/api_core/page_iterator.py"についてコードを見てみると
class Iterator(object): ................... def __init__( self, client, item_to_value=_item_to_value_identity, page_token=None, max_results=None, ): self._started = False # <--- ここ!! self.client = client ....................... def __iter__(self): """Iterator for each item returned. Returns: types.GeneratorType[Any]: A generator of items from the API. Raises: ValueError: If the iterator has already been started. """ if self._started: raise ValueError("Iterator has already started", self) # <--- ここ!!! self._started = True return self._items_iter()
とあります。
一度__iter__が呼ばれてしまうとself._startedがTrueになりValueErrorがなってしまうことがわかります。
ここで最初の__iter__ですが
if len(list(blobs)) == 0:
でリスト数を数えています。このlist(...)で__iter__が呼ばれているので、すでにself._startedがTrueとなっていたわけです。
なので一度別のリスト型変数に入れなおしてからやればエラーになりません。
blob_list_obj = list(blobs) if len(blob_list_obj) == 0: print("Error, No target files....") sys.exit(1) for item in blob_list_obj: print(item.name)