0

パソコンでフォルダを開いているのですが、

OpenFunctions\
    ____Template.py
    function1.py
    function2.py
    ......
    functionx.py

このフォルダは、アプリ全体の機能を拡張するための実験的な目的です。したがって、この場合はセキュリティを考慮せずに、迅速かつ無味乾燥な試みであると考えてみましょう。

私の目的は、functionx.py次のをドロップする____Template.pyと、アプリは新しい関数が利用可能であることを認識し、この新しい結合ファイルで定義された関数を何らかの方法で呼び出すことです。プラグイン システムのようなものですが、少し異なる必要があります。

だから私は、____inspect.pyアプリケーションが入力されたものを知ることができるようにするかもしれないと書いた.

こちらが

____inspect.py

def get_this_file_defined_functions(name_filter = "__"):
    import inspect, sys 
    f = inspect.getmembers(sys.modules[__name__], inspect.isfunction) 
    return [x for x in f if not x[0].startswith(name_filter)] 

def get_this_module_sub_modules(name_filter = "__"):
    import os.path, pkgutil
    pkgpath = os.path.dirname(__file__)
    m = [name for _, name, _ in pkgutil.iter_modules([pkgpath])] 
    return [x for x in m if not x[0].startswith(name_filter)]

def import_sub_modules_under_me(auto_exec_function = "auto_exec"):
    m = get_this_module_sub_modules()
    for i in m:  # need try except later
        exec "global %s; import %s" % (i, i)  
        #this will auto invoke __init__.py if sub modules folder is included
    for i in m:
        try:
            eval(i).eval(auto_exec_function)()
        except AttributeError:
            print "module %s has no function %s", % (i, auto_exec_function) 
        else:
            print "error on execute %s in module %s", % (auto_exec_function, i)

def execute_all_homonymy_functions(exec_function = "exec"):
    m = get_this_module_sub_modules()
    for i in m:
        #I need here for test if the module has been imported
        eval(i).eval(exec_function)()

こちらが

____Template.py

def __you_can_not_see_me(): pass  # because filtered by str.startswith()
def auto_exec(): pass             # this will be auto executed
def you_can_get_me(): pass
def you_can_get_me1(): pass
def you_can_get_me2(): pass

上記のアイデアに基づいて、構造を下に拡張したい

main.py
____inspect.py
OpenFunctions\
    __init__.py
    ____Template.py
    function1.py
    function2.py
    ......
    functionx.py
    module_aa
        \__init__.py
          aa.py
          aa1.py

これは、 5月が次のように見えるmain.py間です__init__.py

import ____inspect
____inspect.import_sub_modules_under_me()
____inspect.execute_all_homonymy_functions("what_ever_i_want")

質問:

  1. 上記の__init__コードは機能しません。これsys.modules[__name__]____inspect、 を呼び出しているが、 OpenFunctionsまたはが必要ではないためです。またはにをmodule_aa渡さないようにする方法はあります か?sys.modules[__name__]import_sub_modules_under_me()main.py__init__.py

  2. execute_all_homonymy_functions()サブモジュールまたは単一のファイルに存在する場合でも、フォルダー内の同じ名前の関数をすべて実行すると思いますが、モジュールが新しく追加された場合、またはソースが実行時に変更された場合に備えて、すべての最新バージョンを呼び出したいと思います。次に、コードを使用したいのですimport aa, reload(aa)が、下のリンクでは間違っていると思われるかもしれません。何か提案はありますか? _ _inspect.pyでマークI need here for test if the module has been importedした問題

    [http://stackoverflow.com/questions/5027352/how-to-test-if-one-python-module-has-been-imported]

  3. また、呼び出す前にファイル内の 1 つの関数の戻り値の型を知りたいので、各関数に装飾を付けることが提案されました。だから私の計画は次のとおりです。

\n

____decorate.py

def attrs(**kwds):
     def decorate(f):
         for k in kwds:
             setattr(f, k, kwds[k])
         return f
     return decorate

functionx.py
import ../____decorate.py

@attrs(argument_types=(int, int,),returns=int)
def __you_can_not_see_me(): pass

@attrs(argument_types=(int, int,),returns=int)
def auto_exec(): pass             # I will be auto executed

@attrs(argument_types=(int, int,),returns=int)
def you_can_get_me(): pass

@attrs(argument_types=(int, int,),returns=int)
def you_can_get_me1(): pass

@attrs(argument_types=(int, int,),returns=int)
def you_can_get_me2(): pass

インスペクトケースで問題なく動作しますか?または、より良い解決策がありますか?

最後のもの: 以下のコード

exec "global %s; import %s" % (i, i) 
eval(i).eval(auto_exec_function)()

見苦しく見えますが、上記の 2 行の代わりになるものはありますか?

ご協力いただきありがとうございます。

Rgs, ケンタッキー州

4

1 に答える 1

2

最後の質問に最初に答えるには、最近のバージョンの Python でモジュールを動的にインポートするには、 を使用importlib.import_module()します。それが目的です。古いバージョンの Python を使用している場合は、代わりに を使用する必要があります(ただし、ドキュメントでその直接的なアプローチの特異性を確認してください。関数が代わりに追加された__import__のには理由があります)。import_module()

最初の質問に答えるには: 呼び出し元の関数のグローバル環境に関する情報を取得する公式に移植可能な方法はないため、最も正しい答えは、__name__必要な場所に引数として渡すことです。

Python でのリロードは、リロード時にすべてが正しく機能するわけではないため、常に少し危険です (多くの標準ライブラリ モジュールでさえ、モジュールまたはそれらが参照するモジュールをリロードすると失敗します)。

Python でのプラグイン アーキテクチャに関する既存の質問に対する回答を調べるために、時間を費やすことを強くお勧めします: Pythonで最小限のプラグイン アーキテクチャを構築する

于 2011-02-18T06:53:40.353 に答える