1

コンパイルとインタプリタの両方が可能なプログラミング言語(Heron)のパッケージとモジュールシステムを設計しようとしています。これまで見てきたことから、Pythonのアプローチが本当に気に入っています。Pythonには豊富なモジュールの選択肢があり、それがその成功に大きく貢献しているようです。

モジュールが2つの異なるコンパイル済みパッケージに含まれている場合、Pythonで何が起こるかはわかりません。データから作成された個別のコピーがありますか、それとも共有されていますか?

これに関連するのは、一連の副次的な質問です。

  1. パッケージをPythonでコンパイルできると仮定するのは正しいですか?
  2. 2つのアプローチ(モジュールデータのコピーまたは共有)の長所と短所は何ですか?
  3. Pythonコミュニティの観点から、Pythonモジュールシステムに広く知られている問題はありますか?たとえば、モジュール/パッケージを拡張するために検討中のPEPはありますか?
  4. コンパイルされた言語ではうまく機能しないPythonモジュール/パッケージシステムの特定の側面はありますか?
4

3 に答える 3

3

さて、あなたはたくさんの質問をしました。ここにもう少し先に進むためのいくつかのヒントがあります:

  1. a。Pythonコードはlexedされ、Python固有の命令にコンパイルされますが、マシンの実行可能コードにはコンパイルされません。「.pyc」ファイルは、既存の.pycタイムスタンプと一致しないPythonコードを実行するたびに自動的に作成されます。この機能はオフにすることができます。これらの手順を確認するには、disモジュールを試してみてください。b。モジュールがインポートされると、モジュールはそれ自体の名前空間で(上から下に)実行され、その名前空間はグローバルにキャッシュされます。別のモジュールからインポートする場合、そのモジュールは再度実行されません。defは単なるステートメントであることを忘れないでください。トレースするために、コードにprint('compiling this module')ステートメントを配置することをお勧めします。

  2. 場合によります。

  3. 最近の機能強化があり、主にロードする必要のあるモジュールの指定に関するものでした。モジュールは相対パスを持つことができるため、巨大なプロジェクトには同じ名前の複数のモジュールが含まれる場合があります。

  4. Python自体はコンパイルされた言語では機能しません。Google for "unladen swallow blog"は、 "a = sum(b)"が実行間で意味を変える可能性がある言語を高速化しようとする苦難を確認するためのものです。コーナーケースを除いて、モジュールシステムはソースコードとコンパイルされたライブラリシステムの間の素晴らしい架け橋を形成します。このアプローチはうまく機能し、PythonのCコード(swigなど)の簡単なラッピングが役立ちます。

于 2009-12-21T16:35:11.727 に答える
3

モジュールはPythonで唯一の真のグローバルオブジェクトであり、他のすべてのグローバルデータはモジュールシステム(sys.modulesをレジストリとして使用)に基づいています。パッケージは、サブモジュールをインポートするための特別なセマンティクスを持つ単なるモジュールです。.pyファイルを.pycまたは.pyoに「コンパイル」することは、ほとんどの言語で理解されているようにコンパイルされません。構文をチェックし、インタープリターで実行されるとモジュールオブジェクトを作成するコードオブジェクトを作成するだけです。

example.py:

print "Creating %s module." % __name__

def show_def(f):
  print "Creating function %s.%s." % (__name__, f.__name__)
  return f

@show_def
def a():
  print "called: %s.a" % __name__

インタラクティブセッション:

>>> import example
# first sys.modules['example'] is checked
# since it doesn't exist, example.py is found and "compiled" to example.pyc
# (since example.pyc doesn't exist, same would happen if it was outdated, etc.)
Creating example module. # module code is executed
Creating function example.a. # def statement executed
>>> example.a()
called: example.a
>>> import example
# sys.modules['example'] found, local variable example assigned to that object
# no 'Creating ..' output
>>> d = {"__name__": "fake"}
>>> exec open("example.py") in d
# the first import in this session is very similar to this
# in that it creates a module object (which has a __dict__), initializes a few
# variables in it (__builtins__, __name__, and others---packages' __init__
# modules have their own as well---look at some_module.__dict__.keys() or
# dir(some_module))
# and executes the code from example.py in this dict (or the code object stored
# in example.pyc, etc.)
Creating fake module. # module code is executed
Creating function fake.a. # def statement executed
>>> d.keys()
['__builtins__', '__name__', 'a', 'show_def']
>>> d['a']()
called: fake.a

あなたの質問:

  1. これらはある意味でコンパイルされますが、Cコンパイラの動作に精通している場合は期待どおりではありません。
  2. isデータが不変である場合、コピーは実行可能であり、オブジェクトID(演算子およびid()Pythonの場合)を除いて共有と区別がつかないはずです。
  3. インポートはコードを実行する場合と実行しない場合があり(常にローカル変数をオブジェクトに割り当てますが、問題は発生しません)、sys.modulesを変更する場合と変更しない場合があります。スレッドにインポートしないように注意する必要があります。通常、すべてのインポートをすべてのモジュールの上部で実行するのが最善です。これにより、カスケードグラフが作成されるため、すべてのインポートが一度に実行され、__ main__が続行され、RealWork™が実行されます。 。
    • 現在のPEPはわかりませんが、すでに多くの複雑な機械が設置されています。たとえば、パッケージは__path__属性(実際にはパスのリスト)を持つことができるため、サブモジュールは同じディレクトリにある必要はなく、これらのパスは実行時に計算することもできます。(以下のmungepathパッケージの例。)独自のインポートフックを作成し、関数内でimportステートメントを使用し、__ import__を直接呼び出すことができます。パッケージとモジュールを操作する他の2〜3のユニークな方法を見つけても驚かないでしょう。
  4. インポートシステムのサブセットは、Cの#includeのようなものに類似している限り、従来のコンパイル言語で機能します。コンパイラで「第1レベル」の実行(モジュールオブジェクトの作成)を実行し、それらの結果をコンパイルできます。ただし、これには重大な欠点があり、モジュールレベルのコードと実行時に実行される関数の実行コンテキストを分離することになります(一部の関数は両方のコンテキストで実行する必要があります)。(Pythonでは、defステートメントやclassステートメントも含め、すべてのステートメントが実行時に実行されることに注意してください。)
    • これが、従来のコンパイル言語が「トップレベル」コードをクラス、関数、およびオブジェクトの宣言に制限し、この2番目のコンテキストを排除する主な理由であると思います。それでも、注意深く管理しない限り、C / C ++(およびその他)のグローバルオブジェクトの初期化の問題が発生します。

mungepath / __ init __。py:

print __path__
__path__.append(".") # CWD, would be different in non-example code
print __path__
from . import example # this is example.py from above, and is NOT in mungepath/
# note that this is a degenerate case, in that we now have two names for the
# 'same' module: example and mungepath.example, but they're really different
# modules with different functions (use 'is' or 'id()' to verify)

インタラクティブセッション:

>>> import example
Creating example module.
Creating function example.a.
>>> example.__dict__.keys()
['a', '__builtins__', '__file__', 'show_def', '__package__',
 '__name__', '__doc__']
>>> import mungepath
['mungepath']
['mungepath', '.']
Creating mungepath.example module.
Creating function mungepath.example.a.
>>> mungepath.example.a()
called: mungepath.example.a
>>> example is mungepath.example
False
>>> example.a is mungepath.example.a
False
于 2009-12-21T17:32:07.917 に答える
1

グローバルデータは、インタープリターレベルでスコープされます。

  1. 「パッケージ」は、それ自体がコンパイルできるモジュールの単なるコレクションであるため、コンパイルできます。
  2. データのスコープが確立されていることを考えると、理解できません。
于 2009-12-21T16:08:18.247 に答える