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)
参考ページ