Как загрузить все модули в папку?
Может ли кто-нибудь предоставить мне хороший способ импорта целого каталога модулей?
У меня есть такая структура:
/Foo
bar.py
spam.py
eggs.py
Я попытался просто преобразовать его в пакет, добавив __init__.py
и выполнив from Foo import *
, но он не работал так, как я надеялся.
Ответы
Ответ 1
Перечислите все файлы Python (.py
) в текущей папке и поместите их как переменную __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')]
Ответ 2
Добавьте переменную __all__
в __init__.py
, содержащую:
__all__ = ["bar", "spam", "eggs"]
См. также http://docs.python.org/tutorial/modules.html
Ответ 3
Обновление в 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 *
не очень хорошая идея по нескольким причинам, включая конфликт имен и усложнение анализа кода.
Ответ 4
Развернувшись на ответ 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'>
Ответ 5
Python, включите все файлы в каталог:
Для новичков, которые просто не могут заставить его работать, кому нужны руки.
-
Создайте папку /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"]
-
Сделайте два файла python: spam.py
и ham.py
в разделе /home/el/foo/hellokitty
-
Определите функцию внутри spam.py:
def spamfunc():
print "Spammity spam"
-
Определите функцию внутри ham.py:
def hamfunc():
print "Upgrade from baloney"
-
Запустите его:
[email protected]:/home/el/foo$ python main.py
spammity spam
Upgrade from baloney
Ответ 6
Я сам устал от этой проблемы, поэтому я написал пакет под названием automodinit для его исправления. Вы можете получить его из http://pypi.python.org/pypi/automodinit/.
Использование выглядит так:
- Включите пакет
automodinit
в ваши зависимости setup.py
.
- Замените все файлы __init__.py следующим образом:
__all__ = ["I will get rewritten"]
# Don't modify the line above, or this line!
import automodinit
automodinit.automodinit(__name__, __file__, globals())
del automodinit
# Anything else you want can go after here, it won't get modified.
Что это! Теперь импорт модуля будет устанавливать __all__ на
список файлов .py [co] в модуле и также импортирует каждый
из этих файлов, как будто вы набрали:
for x in __all__: import x
Поэтому эффект "from M import *" соответствует точно "import M".
automodinit
счастлив работать из ZIP-архивов и поэтому является безопасным ZIP-архивом.
Найл
Ответ 7
Я знаю, что обновляю довольно старую запись, и я попытался использовать automodinit
, но выяснил, что процесс настройки разбит на python3. Итак, на основе ответа 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 *
Затем у вас будут все модули, которые помещаются в загруженный пакет, и если вы напишете новый модуль, он будет также автоматически импортироваться. Разумеется, использовать такие вещи с осторожностью, с великими полномочиями, несет большую ответственность.
Ответ 8
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
__import__(module)
Ответ 9
Я также столкнулся с этой проблемой, и это было моим решением:
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
Итак, в script я хочу, чтобы модули были импортированы в я буду писать:
loadImports('Test/')
from Test import *
Это будет импортировать все из Test
, а файл __init__.py
в Test
теперь будет содержать:
__all__ = ['Foo','Bar']
Ответ 10
Ответ 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
Ответ 11
Пример Anurag с несколькими исправлениями:
import os, glob
modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))
__all__ = [os.path.basename(f)[:-3] for f in modules if not f.endswith("__init__.py")]
Ответ 12
Посмотрите, что ваш __init__.py
определяет __all__
. модули - пакеты doc говорит
Файлы __init__.py
необходимы, чтобы Python рассматривал каталоги как содержащие пакеты; это делается для предотвращения каталогов с общим именем, например строки, из непреднамеренного скрытия допустимых модулей, которые появляются позже на пути поиска модуля. В простейшем случае __init__.py
может быть просто пустым файлом, но он также может выполнять код инициализации для пакета или устанавливать переменную __all__
, описанную ниже.
...
Единственное решение для автора пакета - предоставить явный индекс пакета. Оператор import использует следующее соглашение: если код пакета __init__.py
определяет список с именем __all__
, он считается списком имен модулей, которые должны быть импортированы, когда из импорта пакета * встречается. Автору пакета рекомендуется сохранить этот список в актуальном состоянии при выпуске новой версии пакета. Авторы пакета могут также решить не поддерживать его, если они не видят использования для импорта * из своего пакета. Например, файл sounds/effects/__init__.py
может содержать следующий код:
__all__ = ["echo", "surround", "reverse"]
Это означало бы, что from sound.effects import *
будет импортировать три названных подмодуля звукового пакета.
Ответ 13
Это лучший способ, который я нашел до сих пор:
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())
Ответ 14
Посмотрите на модуль pkgutil из стандартной библиотеки. Это позволит вам делать именно то, что вы хотите, пока у вас есть файл __init__.py
в каталоге. Файл __init__.py
может быть пустым.
Ответ 15
Я создал для него модуль, который не полагается на __init__.py
(или любой другой вспомогательный файл) и заставляет меня вводить только следующие две строки:
import importdir
importdir.do("Foo", globals())
Не забудьте повторно использовать или вносить свой вклад: http://gitlab.com/aurelien-lourot/importdir
Ответ 16
Просто импортируйте их с помощью importlib и добавьте их в __all__
(действие add
необязательно) в __all__
в __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