Как загрузить все модули в папку?
может ли кто-нибудь предоставить мне хороший способ импорта целого каталога модулей?
У меня есть такая структура:
/Foo
bar.py
spam.py
eggs.py
Я попытался просто преобразовать его в пакет, добавив __init__.py
и в from Foo import *
но это не сработало так, как я надеялся.
16 ответов:
добавить
__all__
переменная__init__.py
содержит:__all__ = ["bar", "spam", "eggs"]
Смотрите также http://docs.python.org/tutorial/modules.html
Список всех python (
.py
) файлы в текущей папке и поместите их как__all__
переменная__init__.py
from os.path import dirname, basename, isfile import glob modules = glob.glob(dirname(__file__)+"/*.py") __all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
обновление: сегодня вы, вероятно, хотите использовать .
сделайте каталог Foo пакетом, добавив
__init__.py
. В этом__init__.py
добавить:import bar import eggs import spam
поскольку вы хотите, чтобы он был динамическим (что может быть или не быть хорошей идеей), перечислите все py-файлы со списком 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
etc. из Foo import * это не очень хорошая идея по нескольким причинам, включая столкновения имен и затруднение анализа кода.
расширяя ответ Михаила, я считаю, что не хакерский способ (например, не обрабатывать пути к файлам напрямую) заключается в следующем:
- создать пустой под
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'>
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"
запустить его:
el@apollo:/home/el/foo$ python main.py spammity spam Upgrade from baloney
Я устал от этой проблемы сам, поэтому я написал пакет под названием 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.вот именно! Отныне импорт модуля устанавливается __все__ для список файлов .py[co] в модуле а также будет импортировать каждый из этих файлов, как будто вы набрали:
for x in __all__: import x
поэтому эффект "от импорта M *" точно соответствует "импорту 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
а то наTest
теперь будет содержать:__all__ = ['Foo','Bar']
пример Анурага с парой исправлений:
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")]
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__
. Элемент - пакеты док говоритThe
__init__.py
файлы необходимы для того, чтобы Python рассматривал каталоги как содержащие пакеты; это делается для предотвращения непреднамеренного скрытия допустимых модулей, которые встречаются позже в пути поиска модуля, в каталогах с общим именем, например string. В самом простом случае,__init__.py
может быть просто пустой файл, но он также может выполнять код инициализации упакуйте или установите__all__
переменная, описанная ниже....
единственным решением для автора пакета является предоставление явного индекса пакета. Оператор import использует следующее соглашение: если пакет
__init__.py
код определяет список с именем__all__
, это будет список имен модулей, которые должны быть импортированы, когда из пакета import * встречается. Это зависит от автора пакета, чтобы сохранить этот список в актуальном состоянии, когда новая версия выпущен пакет. Авторы пакета могут также решить не поддерживать его, если они не видят использования для импорта * из своего пакета. Например, файлsounds/effects/__init__.py
может содержать следующий код:
__all__ = ["echo", "surround", "reverse"]
это будет означать, что
from sound.effects import *
импортирует три именованных подмодуля звукового пакета.
Это лучший способ я нашел до сих пор:
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())
import pkgutil __path__ = pkgutil.extend_path(__path__, __name__) for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'): __import__(module)
посмотрите на модуль pkgutil из стандартной библиотеки. Это позволит вам сделать именно то, что вы хотите, пока у вас есть
__init__.py
файл в каталоге. Элемент__init__.py
файл может быть пустым.
Я создал модуль, который не полагается на
__init__.py
(или любой другой вспомогательный файл) и заставляет меня ввести только следующие две строки: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 __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