319

誰かがモジュールのディレクトリ全体をインポートする良い方法を教えてくれませんか?
私はこのような構造を持っています:

/Foo
    bar.py
    spam.py
    eggs.py

__init__.py追加して行うだけでパッケージに変換しようとしましたfrom Foo import *が、期待どおりに機能しませんでした。

4

20 に答える 20

454

.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')]
于 2009-06-29T10:06:25.593 に答える
147

以下を含む__all__変数を追加します。__init__.py

__all__ = ["bar", "spam", "eggs"]

http://docs.python.org/tutorial/modules.htmlも参照してください

于 2009-06-29T09:42:33.830 に答える
69

2017 年に更新:importlib代わりに使用することをお勧めします。

を追加して、Foo ディレクトリをパッケージにします__init__.py。その__init__.py追加で:

import bar
import eggs
import spam

動的にしたいので(これは良い考えかもしれませんし、そうでないかもしれません)、すべてのpyファイルを list dir でリストし、次のようなものでそれらをインポートします:

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 *は、名前の競合やコードの分析を困難にするなど、いくつかの理由からお勧めできません。

于 2009-06-29T11:10:40.363 に答える
43

Mihailの答えを拡張すると、ハックではない方法(ファイルパスを直接処理しないなど)は次のようになります。

  1. の下に空の__init__.pyファイルを作成しますFoo/
  2. 実行する
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'>
于 2011-12-19T02:11:12.577 に答える
42

Python、ディレクトリの下のすべてのファイルを含めます。

手を握る必要がある、それを機能させることができない初心者向け。

  1. フォルダー /home/el/foo を作成し、main.py/home/el/foo の下にファイルを作成します。そこに次のコードを挿入します。

    from hellokitty import *
    spam.spamfunc()
    ham.hamfunc()
    
  2. ディレクトリを作る/home/el/foo/hellokitty

  3. __init__.py下にファイルを/home/el/foo/hellokitty作成し、このコードをそこに入れます。

    __all__ = ["spam", "ham"]
    
  4. 2 つの python ファイルを作成しspam.pyますham.py/home/el/foo/hellokitty

  5. spam.py 内で関数を定義します。

    def spamfunc():
      print("Spammity spam")
    
  6. ham.py 内で関数を定義します。

    def hamfunc():
      print("Upgrade from baloney")
    
  7. それを実行します:

    el@apollo:/home/el/foo$ python main.py 
    spammity spam
    Upgrade from baloney
    
于 2013-12-24T00:08:56.313 に答える
16

私はこの問題にうんざりしていたので、automodinit というパッケージを作成して修正しました。http://pypi.python.org/pypi/automodinit/から取得できます。

使い方はこんな感じです。

  1. automodinitパッケージをsetup.py依存関係に含めます。
  2. すべての __init__.py ファイルを次のように置き換えます。
__all__ = [「書き換えられます」]
# 上の行もこの行も変更しないでください!
automodinit のインポート
automodinit.automodinit(__name__, __file__, globals())
del automodinit
# 他に必要なものは、ここの後に置くことができます。変更されることはありません。

それでおしまい!これ以降、モジュールをインポートすると、モジュール内の .py[co] ファイルのリストに __all__ が設定され、次のように入力したかのように、これらの各ファイルもインポートされます。

for x in __all__: import x

したがって、「from M import *」の効果は「import M」と完全に一致します。

automodinitZIP アーカイブ内から実行できるため、ZIP セーフです。

ニール

于 2012-03-05T02:24:09.297 に答える
16

私はかなり古い投稿を更新していることを知ってautomodinitいます. したがって、Luca の回答に基づいて、この問題に対するより簡単な回答 (.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 *

次に、パッケージ内に配置されているすべてのモジュールをロードします。新しいモジュールを作成すると、それも自動的にインポートされます。もちろん、そのようなものは慎重に使用してください。大きな力には大きな責任が伴います。

于 2016-03-26T02:54:58.540 に答える
6

私もこの問題に遭遇しましたが、これが私の解決策でした:

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']
于 2012-07-30T21:06:25.390 に答える
5

提案された改善点を含むAnurag Unyalの回答

#!/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  
于 2014-06-13T01:28:24.067 に答える
5

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
于 2019-11-26T15:56:51.090 に答える
4

これは私がこれまでに見つけた最良の方法です:

from os.path import dirname, join, isdir, abspath, basename
from glob import glob
pwd = dirname(__file__)
for x in glob(join(pwd, '*.py')):
    if not x.startswith('__'):
        __import__(basename(x)[:-3], globals(), locals())
于 2014-07-02T08:30:27.257 に答える
4

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()モジュールが既にインポートされている場合、モジュールの再インポートを回避することを意図していることに注意してください。

于 2020-03-26T04:27:11.267 に答える
3

あなたが__init__.py定義していることを確認してください__all__モジュール-パッケージドキュメントによると

これらの__init__.pyファイルは、Pythonがディレクトリをパッケージを含むものとして扱うようにするために必要です。これは、文字列などの一般的な名前のディレクトリが、後でモジュール検索パスで発生する有効なモジュールを意図せずに非表示にするのを防ぐために行われます。最も単純なケースで__init__.pyは、空のファイルにすることもできますが、パッケージの初期化コードを実行したり__all__、後で説明する変数を設定したりすることもできます。

..。

唯一の解決策は、パッケージの作成者がパッケージの明示的なインデックスを提供することです。importステートメントは次の規則を使用します。パッケージの__init__.pyコードがという名前のリストを定義している場合__all__、それはfrom packageimport*が検出されたときにインポートする必要があるモジュール名のリストと見なされます。パッケージの新しいバージョンがリリースされたときにこのリストを最新の状態に保つのは、パッケージの作成者の責任です。パッケージの作成者は、パッケージから*をインポートする用途が見当たらない場合は、サポートしないことを決定する場合もあります。たとえば、ファイルsounds/effects/__init__.pyには次のコードが含まれている可能性があります。

__all__ = ["echo", "surround", "reverse"]

これはfrom sound.effects import *、サウンドパッケージの3つの名前付きサブモジュールをインポートすることを意味します。

于 2009-06-29T09:47:46.800 に答える
1

標準ライブラリのpkgutilモジュールを見てください。__init__.pyディレクトリにファイルがある限り、それはあなたが望むことを正確に行うことを可能にします。__init__.pyファイルは空にすることができます。

于 2011-02-08T12:51:32.667 に答える
-1

ネストされたディレクトリ構造がありました。つまり、メイン ディレクトリ内に Python モジュールを含む複数のディレクトリがありました。

次のスクリプトを__init__.pyファイルに追加して、すべてのモジュールをインポートしました

import glob, re, os 

module_parent_directory = "path/to/the/directory/containing/__init__.py/file"

owd = os.getcwd()
if not owd.endswith(module_parent_directory): os.chdir(module_parent_directory)

module_paths = glob.glob("**/*.py", recursive = True)

for module_path in module_paths:
    if not re.match( ".*__init__.py$", module_path):
        import_path = module_path[:-3]
        import_path = import_path.replace("/", ".")
        exec(f"from .{import_path} import *")

os.chdir(owd)

おそらくこれを達成するための最良の方法ではありませんが、他に何も機能させることができませんでした。

于 2021-01-15T21:41:12.180 に答える