Blog Entry  (May 1, 2017, 11:31 p.m.)

Tilo Mitra's avatar

[小ネタ] Pythonでimportの前に関数を実行しなければならないときの苦肉の策

小ネタです。
殆どないケースですが、Pythonでimportの前に関数やメソッドの実行をする要件が出てきたときの策です。

経緯

LinuxでmatplotlibをインストールしてPythonコード上で使用した時に以下のようなエラーが発生しました。

_tkinter.TclError: no display name and no $DISPLAY environment variable

このエラーの解決策は検索するとすぐに出てきて、matplotlibのバックエンドをAggにすればいいというのが回答のようです。(エラーやバックエンドについての詳細は今回は割愛します)

その方法はいくつかあるようで、/etc/matplotlibrcに backend: Agg と記載する方法 1 と、 matplotlib.use('Agg') を使用する方法 2 が検索上位に上がっていました。

今回はそのうち matplotlib.use('Agg') を採用するとします。

問題点

import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot


def plot(data):
    pyplot.plot(data)

上記のようにimportした後に matplotlibu.use('Agg') を呼べば動くのですが、これには問題があって、import順を自動で変更するツール( isort など)を導入していると以下のように書き換えられてしまいます。

import matplotlib
from matplotlib import pyplot

matplotlib.use('Agg')


def plot(data):
    pyplot.plot(data)

matplotlib.use('Agg') from matplotlib import pyplot を書く前にを呼ばなければいけないようで、CIで自動的にコードをチェックする場合などは困ってしまいます。実行時に呼び出し元関数の中でimportするという手も一応はありますが、importする数や関数の数が増えた場合にだんだん煩雑になっていきます。

対策

対策として以下のように実装できます。

try:
    import matplotlib
    matplotlib.use('Agg')
finally:
    from matplotlib import pyplot


def plot(data):
    pyplot.plot(data)

一応はこれで順序の保証ができます。

元の記事へ