16

現在のモジュールが「最上位のスクリプト環境」であっても、関数の実際の現在のモジュールを特定しようとしています (他の場所からインポートされた場合に表示されるように) __main__

奇妙なことのように聞こえるかもしれませんが、背景として、別のマシンで関数をシリアル化し、(引数を含めて) シリアル化を解除する必要があります。そのためには、シリアル化を解除する__main__前に正しいモジュールがインポートされていないことを確認する必要があります (そうしないと、エラーが発生しますAttributeError: 'module' object has no attribute my_fun)。

これまでのところ、私は検査を試みました:

import inspect
print inspect.getmodule(my_fun)

それは私に与えます

<module '__main__' from 'example.py'>

もちろん。また、 を使用して何か便利なものを見つけようとしglobals()ましたが、運が悪かったです。

私が本当に欲しいのは<module 'example' from 'example.py'>. ハックな方法は、次のようなものを使用してファイル名から解析することだと思います

m_name = __main__.__file__.split("/")[-1].replace(".pyc","")

次に、名前でモジュールを見つけますsys.modules[m_name]

これを行うためのよりクリーンな/より良い方法はありますか?

編集:ipythonの「FakeModule」ともう少しグーグルについて学んだ後、私はこの投稿に出くわしました。これは、現在の解決策を含め、私が直面している問題を正確に説明しています(現在のモジュールimport current_moduleを明示的にインポートしcurrent_module.my_fun、 my_fun)。パッケージのユーザーにとって直感的ではない可能性があるため、これを回避しようとしています。

4

6 に答える 6

8

私は実際にこの同じ問題に遭遇しました。

私が使用したのは:

return os.path.splitext(os.path.basename(__main__.__file__))[0]

これは事実上、「ハック」と同じです。正直なところ、私はそれが最善の解決策だと思います。

于 2012-09-05T17:41:30.313 に答える
8

私はこれが時代遅れであることを知っていますが、Python3 で私のために働くより簡単な解決策を見つけました。簡単に言うと、「__main__」ではなく実際のモジュール名も格納するオブジェクトの __spec__ があります。

import inspect
if obj.__class_.__module__ == "__main__":
    print(inspect.getmodule(obj).__spec__.name)
于 2015-04-30T15:33:46.297 に答える
6

編集:振り返ってみると、これまでのところ、最善かつ最もクリーンな解決策は、そもそもこのような状況に陥らないようにすることです。シリアル化されているのがコードである場合は、すべてのシリアル化可能な関数を、メイン プログラム スクリプトによって読み込まれるモジュールに移動します。これにより、ハックや特別なケースを必要とせずに、あらゆる状況下で関数のオリジンを取得できるようになります。

__main__.__file__それが不可能な場合は、元のソリューション (からモジュール名を取得する) が最善かつ最も簡単だと思います。ユーザーにとって直感に反するように見えることが心配な場合は、適切な関数でラップし、その目的を文書化してください。

モジュールを として実行すると__main__、python はそれを通常のモジュール名に関連付けませんimport example。実際、これはおそらくあなたのケースで発生します。そうしないと、モジュールを名前で見つけることができなくなりますsys.modules。モジュールexampleとモジュール__main__は、実際には個別のランタイムオブジェクトです。モジュール変数を明示的に変更するとわかります。 .

于 2012-07-13T22:50:30.690 に答える
2

これを行う 1 つの方法 (おそらく最善の方法ではありませんが、私にとってはうまくいきます) は、次のような方法でモジュールをインポートし__import__て使用することです。getattr

(ここでは、モジュールの動的ロードに関するこの投稿で説明されているいくつかのアイデアを使用しています。)

def dynamic_import(name):
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

tmodule = dynamic_import('modA')
# Print the module name
print tmodule
# Use the module's contents
t = tmodule.myObject()
t.someMethod()

modA.py は次のようになります。

class myObject():
    def someMethod(self):
        print "I am module A"

インポートしたモジュールの名前を取得し、モジュール内のオブジェクトとメソッドを通常の方法で使用できることがわかります。これを実行すると、次のようになります。

python experiment.py 
<module 'modA' from 'modA.pyc'>
I am module A

繰り返しますが、これは「理想的な」方法である場合とそうでない場合がありますが、うまく機能し、ほとんどの場合、望ましくないトレードオフを伴うことはありません。お役に立てれば。

于 2012-05-25T15:04:51.560 に答える
0

既存の回答のいずれも、実際に質問に直接答えているとは思いません__main__

ほとんどの手順で検査を使用しています...

import inspect

def module_name(obj):
    module_name = obj.__module__

    if "__main__" in module_name:
        # get parent modules of object
        mod_obj = inspect.getmodule(obj) # type: module

        # from the filename of the module, get its name
        mod_suffix  = inspect.getmodulename(inspect.getmodule(obj).__file__)

        # join parent to child with a .
        module_name = '.'.join([mod_obj.__package__, mod_suffix])

    return module_name
于 2020-12-08T08:47:30.737 に答える
-1

Python 3.4以降、

importlib.util.find_spec('__main__').name
于 2021-05-05T14:17:48.287 に答える