0

私の質問はthis oneと非常によく似ていますが、私の場合は、パッケージ内で使用されていて、わかりませんなぜ。pythonパッケージ内のすべての関数にデコレータを適用する

project/ 
    package/ 
     __init__.py 
     module_a.py 
     module_b.py 
    main.py 

__init__.py

from .module_a import * 
from .module_b import * 

import types 
# This is the decorator that will be used 
from functools import lru_cache 

for name, obj in list(globals().items()): 
    if isinstance(obj, types.FunctionType): 
     globals()[name] = lru_cache(maxsize=100)(obj) 

module_a.py

from .module_b import b 

def a(arg): 
    return b 

module_b.py

例えば、私はこのようなセットアッププロジェクトを持っています

main.py

import package 

print(package.a.cache_info()) 
print(package.a(None).cache_info()) 
print(package.b.cache_info()) 

パッケージをインポートすると、コードをステップ実行するとき、__init__.pyはうまくglobalsで関数を飾ります。

C:\Users\pbreach\Anaconda3\python.exe C:/Users/pbreach/PycharmProjects/project/main.py 
Traceback (most recent call last): 
CacheInfo(hits=0, misses=0, maxsize=100, currsize=0) 
    File "C:/Users/pbreach/PycharmProjects/project/main.py", line 4, in <module> 
    print(package.a(None).cache_info()) 
AttributeError: 'function' object has no attribute 'cache_info' 

module_amodule_bから輸入する際 bが飾られていないことを意味するだろう:私は main.pyを実行した場合しかし、私は次のエラーを取得します。

なぜこれは2行目でのみ発生しますか?これを達成する方法は何でしょうか?

私は、インポート時に__init__.pyまたはmain.pyのいずれかで飾ることと罰金ですが、私の場合には、それらのかなりの数があるので、むしろpackageに各モジュール内デコレータを適用する必要はありません。

EDIT:

私は__init__.pyglobalsbは、同じ機能の2つの異なるインスタンスがある意味module_aにインポートされたときよりも異なる名前空間であるため、問題があると思います。これを回避する方法はありますか?

答えて

1

からをmodule_aにインポートすると、functools.lru_cacheで飾る機会が得られます。

私が見る唯一の実行可能な代替案は、他のサブモジュールでインポートおよび使用された関数を明示的に装飾してから、他のすべての関数にデコレータを適用することです。あなたの例を使用して

、最初module_bからbを飾ると、その後残りを飾る:私はコメントで述べたように

from package import module_b 

import types 
# This is the decorator that will be used 
from functools import lru_cache 
module_b.b = lru_cache(maxsize=100)(module_b.b) 

from .module_a import * 
from .module_b import * 

for name, obj in list(globals().items()): 
    if isinstance(obj, types.FunctionType): 
     globals()[name] = lru_cache(maxsize=100)(obj) 

別のオプション、その機能が含まれているモジュール内でif句を使用することです他のモジュールに含まれるようになりました。

だから module_b.pyで、あなたはこのような何かを行うことができます:

if __name__ != '__main__': 
    from functools import lru_cache 
    b = lru_cache(b) 

は、これが唯一のモジュールは__main__として実行されていない場合をキャッチ。今度は別のモジュールがこのモジュールを含み、本体が実行されると、__init__.pyの代わりにここで折り返しが実行されます。

+0

これは意味があると思う...唯一の問題は、私のユースケースでは、400以上の異なる機能とインポートを持つ12個のモジュールがありますが、それらの間には 'from。 import module_x' – pbreach

+0

各モジュールのすべての関数を '__init.py__'で繰り返し、* importsの前にデコレータを適用できますか? – pbreach

+1

'module_X'からの関数が' module_Y'でインポートされて使用される前に既にラップされていることを保証する方法で注文することができれば、そうです。もう1つのオプションは、別のサブモジュールにインポートされ、その句の内側に飾られている各サブモジュール内の 'if __name__!= __main __:'のみを使用することができます。 –

関連する問題