16

辞書からモジュールを動的に作成したいのですが、要素を追加することsys.modulesが本当にこれを行うための最良の方法であるかどうか疑問に思っています。例えば

context = { a: 1, b: 2 }
import types
test_context_module = types.ModuleType('TestContext', 'Module created to provide a context for tests')
test_context_module.__dict__.update(context)
import sys
sys.modules['TestContext'] = test_context_module

この点に関する私の当面の目標は、タイミング テスト実行のコンテキストを提供できるようにすることです。

import timeit
timeit.Timer('a + b', 'from TestContext import *')

Timer コンストラクターは文字列だけでなくオブジェクトも受け取るため、これを行う方法は他にもあるようです。ただし、これを行う方法を学ぶことにまだ興味があります。a) 他の潜在的なアプリケーションがあるためです。b) Timer コンストラクターでオブジェクトを使用する方法が正確にわかりません。そうすることは、状況によっては、このアプローチよりも適切ではないことが判明する場合があります。

EDITS/REVELATIONS/PHOOEYS/EUREKAE:

  1. モジュールimport *レベルでのみ動作し、そのステートメントが実行されるコンテキストはモジュール内の関数のコンテキストであるため、タイミング テストの実行に関連するサンプル コードは実際には機能しないことに気付きました。つまり、そのコードを実行するときに使用されるグローバル ディクショナリは のグローバル ディクショナリです。これは、対話型シェルでコードを記述したときの場所だからです。したがって、これを理解するための論理的根拠は少し間違っていますが、それでも有効な質問です。testit__main__

  2. 最初の一連の例で実行されたコードには、新しく作成されたモジュールのコードが実行される名前空間が、それ自体のモジュールはなく、宣言されたモジュールの名前空間であるという望ましくない影響があることがわかりました。これはかなり奇妙で、あらゆる種類の予期しないガラガラヘビのスケッチにつながる可能性があります。したがって、実際にグイドが注目するものである場合、これはこの種のことを意図した方法ではないと確信しています。

  3. Python のインクルード パスにないファイルからモジュールを動的にロードするという、似ているが微妙に異なるケースは、 を使用して非常に簡単に実現できimp.load_source('NewModuleName', 'path/to/module/module_to_load.py')ます。これにより、モジュールが にロードされsys.modulesます。しかし、これは私の質問に実際には答えません。実際には、ファイルシステムのない組み込みプラットフォームでpython を実行している場合はどうなるでしょうか?

私は現在、情報過多のかなりのケースと戦っているので、間違っている可能性がありますが、impモジュールにはこれが可能なものはないようです.

しかし、基本的に、この時点での問題は、オブジェクトのグローバル (つまりモジュール) コンテキストを設定する方法です。もっと具体的に聞いたほうがいいのではないでしょうか?そして、より広い範囲で、オブジェクトを特定のモジュールにシューホーニングしながら、Python にこれを実行させるにはどうすればよいでしょうか?

4

1 に答える 1

3

うーん、1 つ言えることは、timeit関数は実際にはモジュールのグローバル変数を使用してそのコードを実行するということです。だからあなたの例では、あなたは書くことができます

import timeit
timeit.a = 1
timeit.b = 2
timeit.Timer('a + b').timeit()

そしてそれはうまくいくでしょう。しかし、それはモジュールを動的に定義するというより一般的な問題には対処していません。

モジュール定義の問題に関しては、それは間違いなく可能であり、あなたはそれを行うための最良の方法に出くわしたと思います. 参考までに、Python がモジュールをインポートするときの要点は、基本的に次のとおりです。

module = imp.new_module(name)
execfile(file, module.__dict__)

ファイルの代わりに既存の辞書からモジュールの内容をロードすることを除いて、これはあなたがすることと同じようなものです。( docstring 以外のtypes.ModuleTypeとの違いはわかりません。したがって、おそらくそれらを同じ意味で使用できます)imp.new_modulesys.modules

余談import *ですが、あなたのことが関数内で合法であったとしても、奇妙なことに、に渡すステートメントがTimerそれ自体のローカル変数を認識していないように見えるため、問題が発生する可能性があります。extract_context()私は(私が書いた関数です)の名前でPythonブードゥー教を少し呼び出して、ローカルスコープで設定aし、実行しましたb

print timeit.Timer('print locals(); a + b', 'sys.modules["__main__"].extract_context()').timeit()

案の定、locals()含まれているaとの出力b:

{'a': 1, 'b': 2, '_timer': <built-in function time>, '_it': repeat(None, 999999), '_t0': 1277378305.3572791, '_i': None}

しかし、それはまだ不平を言っていNameError: global name 'a' is not definedます。変。

于 2010-06-24T11:46:14.233 に答える