はじめに
RDKitでパスやファイル名に日本語を含むSDFファイルを読み込めないイライラにサヨナラするために調べてみたメモ。
現象
例えば以下のように、パスやファイル名に日本語を含むSDFファイルをSDMolSupplierで読み込もうとする。
sdf_filepath = "テスト\αサンプル.sdf"
sdf_sup = Chem.SDMolSupplier(sdf_filepath)
するとこんなエラーが発生する。
OSError: File error: Bad input file テスト\αサンプル.sdf
どうやらSDMolSupplierがマルチバイト文字に対応してないようである。
このためにわざわざ綿密に計画したフォルダ名を変更するのもイラっと来る。
また、ファイル名を化合物名とした場合などに、ファイル名にギリシャ文字などのマルチバイト文字が含まれるのは実務上よくある話だ。
対処方法
対処方法として以下の方針を立てた。
- ファイルの存在する場所にカレントディレクトリを移動して読み込むようにする。こうすることでフォルダ名を気にする必要がなくなる。
- ファイル名についてはどうしようもないので、一旦ファイル名を変更し、読み込みが終わったらファイル名を元に戻す。読み込み途中で処理が異常終了した場合のロールバック等の考慮が面倒だが他に思いつかない。
やってみよう
対処方針にしたがって先ほどのコードを改良したものを示す。
sdf_filepath = "テスト\αサンプル.sdf"
import os
# カレントディレクトリを保持
current_path = os.getcwd()
# カレントディレクトリをファイルの存在するフォルダに変更
os.chdir(os.path.dirname(sdf_filepath))
# ファイル名を取得
filename = os.path.basename(sdf_filepath)
# ファイル名を一時変更
tmpname = "tmp.sdf"
os.rename(filename, tmpname)
# 一時変更したファイル名でSDFの読み込み
sdf_sup = Chem.SDMolSupplier(tmpname)
for mol in sdf_sup:
if mol is not None:
<処理>
sdf_sup = None
# ファイル名を元に戻す
os.rename(tmpname, filename)
# カレントディレクトリを元に戻す
os.chdir(current_path)
これで無事、読み込みができるようになった。
おわりに
ロールバック等を考慮すると本番システムに組み込むのは怖いが、ちょっとした解析であれば十分実用に使えると思う。