オリジナル:ディープ:Pythonはどのように自動的に不足しているライブラリをインポートするには?
著者:エンドウ猫
Pythonのプロジェクトを書くとき、私たちはしばしばエラーインポートモジュールに障害が発生する場合がありますImportError: No module named 'xxx'
かModuleNotFoundError: No module named 'xxx'
。
通常2つのタイプに分けインポートの失敗は、:1は自分の(すなわち、サフィックスの.pyファイルなど)、およびその他があるインポート・パーティのライブラリを書くためのモジュールをインポートすることです。この記事では、機会を持って、私たちは詳細に、他の関連トピックを議論し、将来的に、後者の場合に焦点を当てています。
問題を解決するために失敗したPythonライブラリをインポートする、実際には、キーが(仮想環境かどうかに注意してください)ライブラリが不足していると一緒にインストール、または適切な代替手段を使用しているオペレーティング環境です。問題は3つのケースに分けられます。
シングル不足しているライブラリモジュール
我々はなく、確かにそれをインストールされている実際の動作環境の、(そのような要求など)の三者のライブラリを使用する必要がある場合は、コードの作成では、あなたが行うことができます。
してみてください: インポート要求を 除いてはImportError: 輸入OSの os.system(「ピップインストールを要求」) のインポート要求を
要求が最初のインストールで、ライブラリを見つけ、その後、インポートすることができない場合は、その旨を書きました。
いくつかのオープンソースプロジェクトでは、我々はまた、(例えばJSONに)次の行が表示されることがあります
試し: 輸入JSONなどのsimplejson 除いはImportError: 輸入 JSON
効果を書いて、優先度の三者インポートライブラリのsimplejson、そうでない場合は、その後、内蔵の標準ライブラリJSONを使用しています。
この書き込みの利点があり、追加のライブラリをインポートする必要がありませんが、それは必要性が標準ライブラリには、代替ライブラリが、それが不可能ではない場合は2つのライブラリの使用は、互換性があることを確実にするという欠点を持っています。
あなたが本当に互換性のある標準ライブラリを見つけることができない場合、あなたはまた、(例えばmy_json.pyなど)独自のモジュールを書くことができますあなたが望むものを達成するために、その後、声明を除いて、それをインポートします。
してみてください: 輸入JSONなどのsimplejsonを 除いてはImportError: 輸入 JSONとしてmy_jsonを
第二に、プロジェクト全体は、ライブラリが不足しています
上記のアイデアは、プロジェクトの開発のためですが、それはいくつかの欠点があります:1、各三者ライブラリのコードでは、ピップインストールされない可能性があり、望ましいことではない; 2、三者の標準ライブラリやライブラリは自分ですることはできません手書きのライブラリアン、どのようにしますか?3、プロジェクトが形成された、これらの変更はどのように行うために行うことを許可されていませんか?
ここで問題があるので:あなたは新しいマシンに展開するというプロジェクトを持って行う方法、それは三者のライブラリの多くを含むが、それらは、マシンにプリインストールされていませんか?
プロジェクトへの準拠について、合意に基づいて、それは通常、「含まれていますrequirements.txt 」の文書を、すべてのプロジェクトの依存関係とそのバージョン番号のレコードが必要。これは、プロジェクトのリリース前に、コマンドが使用しているpip freeze > requirements.txt
が生成されます。
コマンドを使用しますpip install -r requirements.txt
(ファイルディレクトリ内で実行、またはコマンドパス内の全ファイルを書き込む)、それは自動的にすべての依存ライブラリがインストールされて提供します。
プロジェクトが準拠していない、または不正な他の理由のために、私たちは、このような文書を持っていない場合は、あなたはいいですか?
愚かな方法は、それは間違って行くためのプロジェクト稼働して、待ち時間を置くことで、あなたはガイドライブラリを手動でロードプロジェクト遭遇ガイドライブラリは、それをインストールに失敗した後、再度実行して、というように......(1ここでは省略し、失敗に遭遇します1万悪い言語)......
第三に、自動インポート欠落しているライブラリ
より良い方法は、自動的に不足しているライブラリにそれをそこにインポートすることができていますか?
「requirements.txt」ファイルを必要とせずに、元のコードを変更することなく、自動的にライブラリの必要性、それをインポートする方法はありませんか?
もちろんあります!結果を初めて目:
私たちは、例えば、最初の操作は、我々は第2の操作の後、輸入は再び竜巻、竜巻がインストールされていない、見ることができ竜巻、プログラムは、私たちが自動的にダウンロードし、竜巻をインストールするために役立つエラーがないようにします。
私たちの手書きのモジュールコードを自動インストールは次のとおりです。
#以下代码在パイソン3.6.1版本验证通过 インポートSYS インポートOS からのimportlib インポートimport_moduleの クラス自動インストール(): _loaded = セット() @classmethod DEF find_spec(CLS、名前、パス、ターゲット= なし): 場合パスはありませんなしと名前ない でcls._loaded: cls._loaded.add(名) プリント(「インストール」、名) してみてください: 結果= os.system(' PIPがインストール{} ' .format(名)) であれば結果== 0: リターンimport_module(名) 以外Eとして例外: プリント(" 失敗" 、E) リターンなし sys.meta_path.append(自動インストール)
このコードはで使用されsys.meta_path
、それが何であるかどうかを確認するために私たちの最初の印刷?
Pythonのインポート機構3は、実質的に以下の順序で、ディスカバリプロセスです。
- すべてのインポートモジュールをキャッシュする、sys.modulesで検索
- sys.meta_pathで検索し、それがカスタムローダーをサポート
- ライブラリディレクトリの名前のいくつかを記録している、のsys.pathで検索
- 見つからない場合は、投げる
ImportError
例外を
これに留意すべきである、そのようなsys.meta_pathパイソン2とPython 3差で、その大きなとしてPythonの異なるバージョンに変化;新しいPythonの3バージョン(3.4+)において、カスタム・ローダは、実装する必要がありますfind_spec
方法、および使用される初期のバージョンがありますfind_module
。
自動インストールクラスローダカスタムで上記のコードは、自動的にインポートライブラリ成分の目的を達成することができます。説明する必要が、いくつかの奇妙な問題が発生する可能性がありますので、すべて新しくインポートしたライブラリを「ハイジャック」オリジナルのインポート方法を破壊するであろう、このアプローチは、してください注意を払います。
sys.meta_pathの使用Pythonのプローブが属します。プローブ、import hook
ほとんど見過ごさPythonのですが、それは、このようなネットワーク上でライブラリをロードするなど、多くのことを、行うことができ、モジュールは、モジュールをインポートするときに、自動的な遅延ロードなどの不足しているライブラリ、アップロード監査情報を、インストールされた修正ように。
紙面の都合のために、我々は詳細にレイアウトされなくなりました。最終概要について:
- あなたは、単純な3ライブラリまたはインポートの交換を達成するための方法を除いて...試すことができます
- 既知の依存性(例えばrequirements.txt)の合計欠失は、手動でインストールすることができる場合
-
sys.meta_pathを使用すると、自動的に削除ライブラリをインポートすることができます
参考文献:
https://github.com/liuchang0812/slides/tree/master/pycon2015cn
http://blog.konghy.cn/2016/10/25/python-import-hook
https://docs.python.org/3/library/sys.html#sys.meta_path