概要
python2でthreadingモジュールを使用して並列処理を実装した際に、datetimeのstrptime関数がエラーを吐いて、対処法について調べたのでその内容を記す。
検証環境
- windows10
- python2.7.11
再現コード
from datetime import datetime
import threading
def parse_time(datetime_str):
print datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
threads = []
for _ in xrange(20):
thread = threading.thread(target=parse_time,
args=["2018-01-01 12:34:56"])
threads.append(thread)
for thread in threads:
thread.start()
上記のようなコードを書いた場合に、実行時以下のようなエラーを吐く。
Exception in thread Thread-8:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "{実行ファイルまでのPath}", line 5, in parse_time
print datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S.%f")
AttributeError: 'module' object has no attribute '_strptime'
原因
タイトルの通りPython2のstrptimeはスレッドセーフではないらしい。
探したらそれらしいIssueもある。だいぶ昔からある模様
対応
こちらを参考にした
threadingの処理が始まる前に、ダミーで一度呼べば良いそう。
なので先程のコードだと以下のように、threadがスタートする前に仮の呼び出しを一度行えばエラーが解消される。
"""前略"""
# 以下を追加。
datetime.strptime("2018-01-01 12:34:56", "%Y-%m-%d %H:%M:%S")
threads = []
for _ in xrange(20):
thread = threading.thread(target=parse_time,
args=["2018-01-01 10:10:00.123456"])
threads.append(thread)
"""後略"""
まとめ
動くようにはなったものの、対応方法が完全にバッドノウハウで悲しい。
なお、Python3.6.4で同様の処理を試したところ問題なく動作した。
Maya等のDCCでも早くPython3が使えるようになってほしい。