コマンドラインからGoogle Cloud Storage (GCS) を操作することができる gsutil
パッケージ。
GCSからファイルをコピーする際に gsutil cp
コマンドを使うのだが、複数ファイルの場合直列に処理すると遅い。
そこで並列に処理するために gsutil -m cp
を実行したら以下のエラーが発生した。
gsutil TypeError: cannot pickle '_io.TextIOWrapper' object
一体何が間違っているのだろうか。
今回はこの gsutil TypeError: cannot pickle '_io.TextIOWrapper' object
のエラー原因と対処法について解説する。
この記事を書いている人
記事を読むメリット
エラー内容
現象としては gsutil cp
で順番に1つずつコピーはできるが、並列に処理する gsutil -m cp
ではエラーになる。
エラー内容を知るために今一度エラーメッセージを見てみる。
gsutil TypeError: cannot pickle '_io.TextIOWrapper' object
まず TypeError
なので変数の型が合っていない。
そして cannot pickle
以下のメッセージは _io.TextIOWrapper
形式のオブジェクトをpicle、つまり変数のままファイル出力できないと言っている。
エラー原因
gsutil TypeError: cannot pickle '_io.TextIOWrapper' object
の根本原因、それはPythonのバージョン。
実はこのエラーPython3.8からMacOS上での動作が一部変わった事に起因している。
Tracking this down, this error comes from a change in Python 3.8 in the multiprocessing library:
Changed in version 3.8: On macOS, the spawn start method is now the default. The fork start method should be considered unsafe as it can lead to crashes of the subprocess. See bpo-33725.
Spawn is being run for those using MacOs and Python 3.8+ by default since nothing is explicitly set either through get_context or set_start_method.
エラーの解決方法
gsutil TypeError: cannot pickle '_io.TextIOWrapper' object
の原因はPythonのバージョン。
であれば解決方法はPythonのバージョンを変更する。
具体的にはPython3.8ではなくPython3.7系を使えばこのエラーは出ない。
そしてPython3.7のインストール方法だが、Linux環境にPythonをインストールする方法と変わらない。
pyenvをインストールして、pyenvを使ってPython3.7をインストールし、最後にPython3.7をデフォルトにするだけだ。
注意点があるとすればMacOSの現在のデフォルトシェルはbashではなくzshである点。
pyenvインストール後の環境変数の設定をzsh用にするか、もしくはデフォルトの起動シェルをbashに変更するかする必要がある。
自分でやるときも「Linuxと同じだなぁ」と思いながら作業してたけど、pyenvインストール後に
zsh:command not found
が出て、「あれ?pyenv動かないぞ?」ってなりましたもん。【エラー】gsutil TypeError: cannot pickle '_io.TextIOWrapper' object まとめ
gsutil TypeError: cannot pickle '_io.TextIOWrapper' object
の原因は Python3.8からMacOSでの挙動が少し変わったから。
解決方法はPython3.8の代わりに3.7を使う。
ちなみにMacのターミナルの起動シェルをzshからbashに変える方法については以下にまとめたので、もし興味があれば見てみてほしい。
あわせて読みたい