以前の開発者による厄介な決定を整理しているコードベースがあります。多くの場合、彼は次のようなことをしました。
from scipy import *
from numpy import *
...もちろん、これは名前空間を汚染し、モジュール内の属性がどこから来たのかを知ることを困難にします。
Python でこれを分析して修正する方法はありますか? 誰かがこれのためのユーティリティを作りましたか? そうでない場合、このようなユーティリティをどのように作成できますか?
以前の開発者による厄介な決定を整理しているコードベースがあります。多くの場合、彼は次のようなことをしました。
from scipy import *
from numpy import *
...もちろん、これは名前空間を汚染し、モジュール内の属性がどこから来たのかを知ることを困難にします。
Python でこれを分析して修正する方法はありますか? 誰かがこれのためのユーティリティを作りましたか? そうでない場合、このようなユーティリティをどのように作成できますか?
私は、PurityLake と Martijn Pieters の支援付きマニュアル ソリューションがおそらく最善の方法だと思います。しかし、これをプログラムで行うことは不可能ではありません。
まず、モジュールの辞書に存在する、コードで使用される可能性のあるすべての名前のリストを取得する必要があります。私はあなたのコードがダンダー関数などを直接呼び出していないと仮定しています.
inspect.getmodule()
次に、各オブジェクトが最初に定義されたモジュールを見つけるために使用して、それらを反復処理する必要がありますfrom foo import *
。numpy
およびscipy
モジュールで定義されたすべての名前のリストを作成します。
foo
これで、その出力を取得して、それぞれをに置き換えることができますnumpy.foo
。
ということで、まとめると以下のようになります。
for modname in sys.argv[1:]:
with open(modname + '.py') as srcfile:
src = srcfile.read()
src = src.replace('from numpy import *', 'import numpy')
src = src.replace('from scipy import *', 'import scipy')
mod = __import__(modname)
for name in dir(mod):
original_mod = inspect.getmodule(getattr(mod, name))
if original_mod.__name__ == 'numpy':
src = src.replace(name, 'numpy.'+name)
elif original_mod.__name__ == 'scipy':
src = src.replace(name, 'scipy.'+name)
with open(modname + '.tmp') as dstfile:
dstfile.write(src)
os.rename(modname + '.py', modname + '.bak')
os.rename(modname + '.tmp', modname + '.py')
いずれかの仮定が間違っていても、コードを変更するのは難しくありません。また、tempfile.NamedTemporaryFile
一時ファイルで誤って上書きしないようにするために、およびその他の改善を使用することをお勧めします。(クロスプラットフォームで何かを書くという頭痛の種に対処したくなかっただけです。Windows で実行していない場合は簡単です。) そして、エラー処理を追加します。もちろん、おそらくいくつかのレポートも追加します。
はい。インポートを削除し、モジュールでリンターを実行します。
を使用することをお勧めしflake8
ますが、スタイル エラーに関する多くのノイズも発生する可能性があります。
インポートを削除してコードを実行しようとするだけでは、おそらく十分ではありません。正しい入力で正しいコード行を実行するまで、多くの名前エラーは発生しないからです。代わりに、リンターは解析によってコードを分析し、コードNameError
を実行することなく潜在的な を検出します。
これはすべて、信頼できる単体テストがないか、テストが十分な範囲を提供していないことを前提としています。
この場合、複数の from module import *
行があり、欠落している名前ごとに、どのモジュールがその名前を提供したかを把握する必要があるという点で、少し面倒になります。これには手動の作業が必要になりますが、モジュールを Python インタープリターにインポートして、不足している名前がそのモジュールで定義されているかどうかをテストするだけです。
>>> import scipy, numpy
>>> 'loadtxt' in dir(numpy)
True
numpy
この特定のケースでは、とscipy
モジュールの間に重複があることを考慮する必要があります。両方のモジュールで定義された任意の名前については、最後にインポートされたモジュールが優先されます。
行をそのままにしておくと from module import *
、リンターが NameErrors を発生させる可能性のある名前を検出できなくなることに注意してください。
わかりました、これは私があなたができると思うことです、プログラムを壊してください。インポートを削除し、行われたエラーに注意してください。次に、必要なモジュールのみをインポートします。これには時間がかかる場合がありますが、これが私が知っている唯一の方法です。誰かが役立つツールを知っていれば、喜んで驚かれることでしょう。
編集:ああ、リンター、私はそれについて考えていませんでした。