私は通常、このパターンをPython作業しているプロジェクトごとに少なくとも1回見ます。たとえば、Djangoプロジェクトでは、これはしばしば基本設定ファイル:
try:
from .local_settings import *
except ImportError:
pass
また:
try:
import simplejson as json
except ImportError:
import json
これはいつも私を少しだけ悩ませてきました。モジュールが正常にインポートされた後、ImportError
自体がトリガーされた場合はどうなりますか?たとえば、最初の例では、local_settings
モジュールは存在しますが、次にlocal_settings
は存在しないモジュールをインポートしようとします。
これは、オプションのモジュールをインポートする最も安全な方法ですか、この機能を実現するためのより良い方法がありますか、それともコンテキスト/使用法に依存しますか?
一般的に、インポートするオプションの依存関係はそれ自体で機能することが想定されています。必要なtransitive依存関係が欠落しているために、欠落しているオプションの依存関係をインポートしようとしても、インポートできなくてもほとんど違いはありません。
言い換えると、プログラムがインストールされていない、またはsimplejson
の依存関係がインストールされていないために、プログラムがsimplejson
が使用できないことを気にする必要があるのはなぜですか?どちらの方法でもsimplejson
は使用できません。
オプションの依存関係の場合、推移的な依存関係を含め、依存関係が正しくインストールされていることを確認するのはパッケージインストーラーの役割です。
local_settings
のようなものについては、実際に推移的なImportError
がマスクされる(小さな)リスクがあります。キャッチされたImportError
例外は、いつでもレベルDEBUGなどでログに記録して、例外の原因を簡単に確認できます。
try:
from .local_settings import *
except ImportError:
log.debug('local_settings failed to import', exc_info=True)
logging
パッケージは、exc_info
をtrueに設定したときに後で検査できるように、ログに例外情報を含めます。
別のオプションは warnings
module で警告を発行することです。標準ライブラリには ImportWarning
class があります:
import warnings
try:
from .local_settings import *
except ImportError:
warnings.warn('local_settings failed to import', ImportWarning)
これは、モジュールにインポート時の副作用がないことを前提として、一般的に安全です。
インポートされたモジュールがインポート時に例外(ImportError
だけでなく)を発生させる場合、 それはsys.modules
から削除されます。これは、他のコードがモジュールをインポートしようとした場合、部分的に初期化されたモジュールを取得しないことを意味します。代わりに、Pythonはモジュールをもう一度ロードしようとし、おそらくImportError
で失敗します。
モジュールにインポート時の副作用がある場合、これらの効果は元に戻されないため、これにより問題が発生する可能性があります。特に、問題のあるモジュールが成功したが別のモジュールをインポートした場合、後者はsys.modules
から削除されません。この特定の副作用が問題になることはめったにありませんが、一部の副作用はより厄介な場合があります。