はじめに
RDKitのSDMolSupplierでSDFファイルを読み込むと、ファイルを解放してくれない時があり、対処方法を調べたメモ
現象
例えば以下のようにSDFファイルを読み込んで処理をした後、SDFファイルのファイル名を変更してみる。
tmpname = "hoge.sdf"
sdf_sup = Chem.SDMolSupplier(tmpname)
for mol in sdf_sup:
if mol is not None:
<省略>
#ファイル名を変更する。
os.rename(tmpname, "hogehoge.sdf")
するとこんなエラーが発生する。
PermissionError: [WinError 32] プロセスはファイルにアクセスできません。別のプロセスが使用中です。: 'hoge.sdf' -> 'hgoehoge.sdf'
どうやらファイルがきちんと解放されていないようである。
対処方法
2点方法が見つかったので、それぞれ記載する。
方法1
SDMolSupplierクラスはcloseメソッドを持たないため、明示的に解放することができない。そこで以下のようにSDMolSupplierのインスタンスを保持している変数にNoneをいれ、インスタンスそのものを解放してあげればよい。まさに目から鱗である。
sdf_sup = None
これを実行した後であれば、ファイル名の変更がうまくいく。
方法2
もう一つは、参考文献にあるように、SDMolSupplierの代わりにcloseメソッドを持つForwardSDMolSupplierを利用する方法である。
この場合withを用いた以下のような処理となる。
tmpname = "hoge.sdf"
with open(tmpname, 'rb') as reader:
sdf_sup = Chem.ForwardSDMolSupplier(reader)
for mol in sdf_sup:
if mol is not None:
<省略>
# ファイル名を変更する
os.rename(tmpname, filename)
これでもうまく解放されることが分かる。
なお、ForwardSDMolSupplierを用いるとzipファイルからも読み込んだりすることができるので便利である。