2017-03-09 8 views
4

コードでimport posixを使用すると、(CPython 3.6.0の)バックグラウンドで何が起こりますか?このモジュールには__file__属性はありません。冗長モードでインタプリタを起動すると、私はこの行を参照してください。ここで、 `posix`という名前は/ importステートメントによって解決されますか?

import 'posix' # <class '_frozen_importlib.BuiltinImporter'> 

を新たにopenenedインタプリタで既にsys.modulesに存在だし、それをインポートすると、既存のモジュールに名前をバインドします。

私のプラットフォーム上で実装の詳細os.lstatを調べて、os.statを使用するかどうかを判断しています。

+1

ソースコードをお探しの場合は、[こちら](https://github.com/python/cpython/blob/master/Modules/posixmodule.c#L2420)、それはC言語です。 – user2357112

+0

ありがとう。また、CコードがPythonオブジェクトにどのようにバインドされているかを知ることにも興味があります。 – wim

答えて

3

ここには、必要以上に詳細があります。


posixは組み込みモジュールです。 「組み込みモジュール」が聞こえたら、普通の標準ライブラリモジュールを考えるか、C言語で書かれたモジュールを考えるかもしれませんが、posixはほとんどのものよりも組み込みです。

posixモジュールは、Cで書かれています(Modules/posixmodule.c)。しかし、ほとんどのCモジュール(標準ライブラリCモジュールでさえ)は.soまたは.pydのファイルにコンパイルされ、通常のPythonモジュールのようにインポートパスに配置されますが、posixはPython実行可能ファイル自体にコンパイルされます。 CPythonのインポート・システムの内部の詳細の


PyImport_Inittab arrayされる:これはとモジュールの名前とCモジュールの初期化機能から成るstruct _inittab Sのアレイである

extern struct _inittab _PyImport_Inittab[]; 

struct _inittab *PyImport_Inittab = _PyImport_Inittab; 

その名前。ここにリストされているモジュールは組み込みです。

この配列の初期値は_PyImport_Inittabです。これはModules/config.c(またはご使用のOSによってはPC/config.c)ですが、ここでは該当しません。残念ながら、Modules/config.cはPythonのビルドプロセス中にModules/config.c.inから生成されるので、私はあなたのソースコードのリンクを表示することはできませんが、ここで私は、ファイルを生成するとき、それがどのように見えるの一部です:

struct _inittab _PyImport_Inittab[] = { 

     {"_thread", PyInit__thread}, 
     {"posix", PyInit_posix}, 
     // ... 

をあなたが見ることができるようにposixモジュールのエントリが、モジュール初期化ファンクションPyInit_posixとともにあります。インポート・システムの一部として


モジュールをロードしようとしたとき、Pythonはsys.meta_path、モジュールfindersのリストを通過します。これらのファインダーの1つはsys.path検索を実行する責任がありますが、他の1つは_frozen_importlib.BuiltinImporterであり、posixなどの組み込みモジュールを検索します。

@classmethod 
def find_spec(cls, fullname, path=None, target=None): 
    if path is not None: 
     return None 
    if _imp.is_builtin(fullname): 
     return spec_from_loader(fullname, cls, origin='built-in') 
    else: 
     return None 

"posix"名前をPyImport_Inittabを検索する_imp.is_builtinを使用しています:Pythonはそのファインダーをしようとすると、それはファインダーのfind_specメソッドを実行します。検索で名前が見つかるので、find_specは、組み込みモジュールのローダーがこのモジュールの作成を処理する必要があるという事実を表すモジュール仕様を返します。委譲

@classmethod 
def create_module(self, spec): 
    """Create a built-in module""" 
    if spec.name not in sys.builtin_module_names: 
     raise ImportError('{!r} is not a built-in module'.format(spec.name), 
          name=spec.name) 
    return _call_with_frames_removed(_imp.create_builtin, spec) 

:(。。ローダspec_from_loader第2引数でBuiltinImporterファインダーローダの両方であるので、それは、ここでcls'S)

Pythonは、モジュールオブジェクトを生成するためにローダーのcreate_module方法を実行します_imp.create_builtinに変更され、モジュール名としてPyImport_Inittabが検索され、対応する初期化関数が実行されます。

_call_with_frames_removed(x, y)だけx(y)呼び出しますが、あなたはあなたの輸入が間違って行くスタックトレースにこれらのフレームを見ることはない理由ですスタックトレースからimportlibフレームを除去するために魔法の指標としてpart of the import system扱い、それを。)


多くのコードパスを表示したい場合は、実装のC部分のほとんどが存在するPython/import.cと、Python/ceval.cというインポート実装のほとんどが存在するLib/importlib/_bootstrap.pyを参照してください。ここでは、バイトコードインタープリタループが生きているので、importステートメントが開始され、インポート機構のより多くのコア部分に到達します。

関連文書にはsection of the language reference on the import systemとPEP 451302が含まれています。組み込みモジュールについてはあまり書かれていませんが、他のプログラムでPythonを埋め込んでいる人に向けてa bit of documentationをターゲットにしていましたが、PyImport_Inittabを変更したいと思っていたので、sys.builtin_module_namesというリストがあります。

関連する問題