誰かがモジュールのディレクトリ全体をインポートする良い方法を私に提供できますか?
私はこのような構造を持っています:
/Foo
bar.py
spam.py
eggs.py
追加__init__.pyして実行するfrom Foo import *だけでパッケージに変換しようとしましたが、期待したとおりに機能しませんでした。
誰かがモジュールのディレクトリ全体をインポートする良い方法を私に提供できますか?
私はこのような構造を持っています:
/Foo
bar.py
spam.py
eggs.py
追加__init__.pyして実行するfrom Foo import *だけでパッケージに変換しようとしましたが、期待したとおりに機能しませんでした。
回答:
.py現在のフォルダー内のすべてのpython()ファイルをリストし、それらを__all__変数として__init__.py
from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
if not os.path.basename(f).startswith('_')または少なくとも少なくともif not f.endswith('__init__.py')リストの理解の終わりまでです
os.path.isfile(f)てくださいTrue。これは、壊れたシンボリックリンクやディレクトリsomedir.py/(
from . import *設定した後、__all__あなたはサブモジュールを使用して利用できるようにしたい場合.(例えばとしてmodule.submodule1、module.submodule2など)。
以下__all__を__init__.py含む変数を追加します。
__all__ = ["bar", "spam", "eggs"]
moduleName.varNameref を使用する必要があります。stackoverflow.com/a/710603/248616
2017年の更新:おそらくimportlib代わりに使用したいでしょう。
を追加して、Fooディレクトリをパッケージにし__init__.pyます。その__init__.py追加:
import bar
import eggs
import spam
あなたはそれを動的にしたいので(それは良い考えかもしれないしそうでないかもしれません)、リストdirですべてのpyファイルをリストし、次のようなものでそれらをインポートしてください:
import os
for module in os.listdir(os.path.dirname(__file__)):
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
del module
次に、コードから次のようにします。
import Foo
これでモジュールにアクセスできます
Foo.bar
Foo.eggs
Foo.spam
from Foo import *名前の衝突やコードの分析が困難になるなど、いくつかの理由から、などはお勧めできません。
__import__ハックっぽいので、名前を追加してスクリプトの最後に__all__置く方がいいと思いfrom . import *ます
__import__は一般的な用途ではなく、によって使用されinterpreterますimportlib.import_module()。代わりに使用してください。
from . import eggsでは、__init__.pyPythonがインポートできるようになる前に、私は等をしなければなりませんでした。上のディレクトリでしようとすると、import eggs私だけが取得ModuleNotFoundError: No module named 'eggs'します。import Foomain.py
Mihailの答えを拡張すると、ハッキングをしない方法(ファイルパスを直接処理しないなど)は次のようになります。
__init__.py下に空のファイルを作成するFoo/import pkgutil
import sys
def load_all_modules_from_dir(dirname):
for importer, package_name, _ in pkgutil.iter_modules([dirname]):
full_package_name = '%s.%s' % (dirname, package_name)
if full_package_name not in sys.modules:
module = importer.find_module(package_name
).load_module(full_package_name)
print module
load_all_modules_from_dir('Foo')
あなたは得るでしょう:
<module 'Foo.bar' from '/home/.../Foo/bar.pyc'>
<module 'Foo.spam' from '/home/.../Foo/spam.pyc'>
RuntimeWarningメッセージは、full_package_nameをまったく使用しないことでも回避できますimporter.find_module(package_name).load_module(package_name)。
RuntimeWarningエラーは、親(AKAのDIRNAME)をインポートすることにより、(ほぼ間違いなく醜い方法で)を回避することができます。これを行う1つの方法は- if dirname not in sys.modules: pkgutil.find_loader(dirname).load_module(dirname)です。もちろん、これdirnameは単一コンポーネントの相対パスの場合にのみ機能します。スラッシュはありません。個人的には、代わりにベースのpackage_nameを使用する@Artfunkelのアプローチを好みます。
手を握る必要があるだけで仕事を始められない初心者向け。
/ home / el / fooフォルダーを作成し、main.py/ home / el / fooの下にファイルを作成します。
from hellokitty import *
spam.spamfunc()
ham.hamfunc()ディレクトリを作る /home/el/foo/hellokitty
__init__.py下にファイルを作成し/home/el/foo/hellokitty、このコードをそこに配置します。
__all__ = ["spam", "ham"]2つのpythonファイルを作成しますspam.pyとham.py下/home/el/foo/hellokitty
spam.py内で関数を定義します。
def spamfunc():
print("Spammity spam")ham.py内で関数を定義します。
def hamfunc():
print("Upgrade from baloney")それを実行します:
el@apollo:/home/el/foo$ python main.py
spammity spam
Upgrade from baloneyimport *はPythonのコーディング慣行としては好ましくないと見なされています。それなしでこれをどのように行うのですか?
私は自分でこの問題に飽きたので、それを修正するためにautomodinitというパッケージを書きました。http://pypi.python.org/pypi/automodinit/から取得できます。
使い方は次のとおりです:
automodinitパッケージをsetup.py依存関係に含めます。__all__ = [「書き直します」] #上記の行またはこの行を変更しないでください! automodinitのインポート automodinit.automodinit(__ name__、__file__、globals()) del automodinit #他に必要なものはここから移動できますが、変更されません。
それでおしまい!これ以降、モジュールをインポートすると、__ all__がモジュール内の.py [co]ファイルのリストに設定され、入力したかのようにそれらの各ファイルもインポートされます。
for x in __all__: import x
したがって、「from M import *」の効果は「import M」と完全に一致します。
automodinit ZIPアーカイブ内から実行できるため、ZIPセーフです。
ニアル
かなり古い投稿を更新していることを知っているので、を使用automodinitしてみましたが、python3のセットアッププロセスが壊れていることがわかりました。だから、ルカの答えに基づいて、私はこの問題に対してより簡単な答え-.zipでは機能しないかもしれない-を思いついたので、私はここでそれを共有する必要があると考えました:
__init__.pyモジュール内yourpackage:
#!/usr/bin/env python
import os, pkgutil
__all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)]))
以下の別のパッケージ内yourpackage:
from yourpackage import *
次に、パッケージ内に配置されたすべてのモジュールが読み込まれ、新しいモジュールを作成すると、自動的に自動的にインポートされます。もちろん、そのようなことを注意深く使用することには、大きな力があり、大きな責任が伴います。
私もこの問題に遭遇し、これが私の解決策でした:
import os
def loadImports(path):
files = os.listdir(path)
imps = []
for i in range(len(files)):
name = files[i].split('.')
if len(name) > 1:
if name[1] == 'py' and name[0] != '__init__':
name = name[0]
imps.append(name)
file = open(path+'__init__.py','w')
toWrite = '__all__ = '+str(imps)
file.write(toWrite)
file.close()
この関数は、(指定されたフォルダーに)という名前のファイルを作成します。このファイルには、フォルダー内のすべてのモジュールを保持__init__.pyする__all__変数が含まれています。
たとえば、次の名前のフォルダがTest
あります。
Foo.py
Bar.py
そのため、スクリプトにモジュールをインポートしたいので、次のように記述します。
loadImports('Test/')
from Test import *
これによりTest、すべてがインポートされ、__init__.pyファイルにTestは以下が含まれます。
__all__ = ['Foo','Bar']
Anurag Uniyalの回答と提案された改善!
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import os
import glob
all_list = list()
for f in glob.glob(os.path.dirname(__file__)+"/*.py"):
if os.path.isfile(f) and not os.path.basename(f).startswith('_'):
all_list.append(os.path.basename(f)[:-3])
__all__ = all_list
あなたの__init__.py定義を参照してください__all__。モジュール-パッケージドキュメントは言います
これらの
__init__.pyファイルは、Pythonがディレクトリをパッケージを含むものとして扱うために必要です。これは、文字列などの一般的な名前のディレクトリが、後でモジュール検索パスで発生する有効なモジュールを誤って非表示にしないようにするために行われます。最も単純なケースで__init__.pyは、空のファイルにすることができ__all__ますが、後で説明するように、パッケージの初期化コードを実行したり、変数を設定したりすることもできます。...
唯一の解決策は、パッケージ作成者がパッケージの明示的なインデックスを提供することです。importステートメントは次の規則を使用します。パッケージの
__init__.pyコードがという名前のリストを定義する__all__場合、from package import *が検出されたときにインポートする必要があるモジュール名のリストと見なされます。パッケージの新しいバージョンがリリースされたときにこのリストを最新に保つのはパッケージ作成者の責任です。パッケージの作成者は、パッケージから*をインポートする使用法が見当たらない場合、サポートしないことを決定することもあります。たとえば、ファイルsounds/effects/__init__.pyには次のコードを含めることができます。
__all__ = ["echo", "surround", "reverse"]これは
from sound.effects import *、サウンドパッケージの3つの名前付きサブモジュールをインポートすることを意味します。
使用してimportlib追加するんだ唯一の事をされます
from importlib import import_module
from pathlib import Path
__all__ = [
import_module(f".{f.stem}", __package__)
for f in Path(__file__).parent.glob("*.py")
if "__" not in f.stem
]
del import_module, Path
error: Type of __all__ must be "Sequence[str]", not "List[Module]"。__all__このimport_moduleベースのアプローチを使用する場合、定義は必要ありません。
標準ライブラリのpkgutilモジュールを見てください。__init__.pyディレクトリにファイルがある限り、必要な操作を正確に実行できます。__init__.pyファイルは空にすることができます。
そのためのモジュールを作成しました。これは__init__.py(またはその他の補助ファイル)に依存せず、次の2行のみを入力します。
import importdir
importdir.do("Foo", globals())
自由に再利用または貢献してください:http : //gitlab.com/aurelien-lourot/importdir
それらをimportlibによってインポートし、パッケージのに再帰的に__all__(addアクションはオプションです)に追加し__init__.pyます。
/Foo
bar.py
spam.py
eggs.py
__init__.py
# __init__.py
import os
import importlib
pyfile_extes = ['py', ]
__all__ = [importlib.import_module('.%s' % filename, __package__) for filename in [os.path.splitext(i)[0] for i in os.listdir(os.path.dirname(__file__)) if os.path.splitext(i)[1] in pyfile_extes] if not filename.startswith('__')]
del os, importlib, pyfile_extes
py
from . import *が十分でない場合、これはtedによる回答よりも優れています。特に、__all__このアプローチではの使用は必要ありません。
"""Import all modules that exist in the current directory."""
# Ref https://stackoverflow.com/a/60861023/
from importlib import import_module
from pathlib import Path
for f in Path(__file__).parent.glob("*.py"):
module_name = f.stem
if (not module_name.startswith("_")) and (module_name not in globals()):
import_module(f".{module_name}", __package__)
del f, module_name
del import_module, Path
これmodule_name not in globals()は、モジュールが既にインポートされている場合、再インポートを回避することを目的としていることに注意してください。これは、循環インポートの危険を冒す可能性があるためです。