誰かがモジュールのディレクトリ全体をインポートする良い方法を私に提供できますか?
私はこのような構造を持っています:
/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.varName
ref を使用する必要があります。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__.py
Pythonがインポートできるようになる前に、私は等をしなければなりませんでした。上のディレクトリでしようとすると、import eggs
私だけが取得ModuleNotFoundError: No module named 'eggs'
します。import Foo
main.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 baloney
import *
は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()
は、モジュールが既にインポートされている場合、再インポートを回避することを目的としていることに注意してください。これは、循環インポートの危険を冒す可能性があるためです。