Как загрузить все модули в папке?

Может ли кто-нибудь предоставить мне хороший способ импорта целого каталога модулей?
У меня есть такая структура:

<code>/Foo
    bar.py
    spam.py
    eggs.py
</code>

Я пытался просто преобразовать его в пакет, добавив__init__.py и делаюfrom Foo import * но это не сработало так, как я надеялся.

 yangmillstheory01 окт. 2016 г., 07:28
Это Pythonic или рекомендуется? "Явное лучше, чем неявное."
 balpha♦29 июн. 2009 г., 11:42
Theв это .py путь довольно правильный. Можете ли вы опубликовать код, который не работал?
 S.Lott29 июн. 2009 г., 12:07
Можете ли вы определить "не работает"? Что произошло? Какое сообщение об ошибке вы получили?

Ответы на вопрос(16)

import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
for imp, module, ispackage in pkgutil.walk_packages(path=__path__, prefix=__name__+'.'):
  __import__(module)

Добавить__all__ Переменный на__init__.py содержащий:

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

Смотрите такжеhttp: //docs.python.org/tutorial/modules.htm

 Nam G VU30 мая 2017 г., 08:34
Я узнал сам - чтобы использовать переменную / объект, определенный в этих модулях, мы должны использовать полный путь ссылки, например,moduleName.varName ссылка Stackoverflow.com / а / 710603/248616
 hayavuk08 сент. 2014 г., 18:32
Комбинацияos.listdir(), некоторая фильтрация, удаление.py расширение и__all__.
 Nam G VU30 мая 2017 г., 08:08
У меня не работает пример кода здесь Github.com / namgivu / питон-импорт-все / BLOB / Master / error_app.py Может я что-то там пропускаю?
 martineau27 окт. 2017 г., 20:01
@ NamGVU: этот код вмой отве к связанному вопросу импортирует имена всех общедоступных подмодулей в пространство имен пакета.
 Evan Fosmark29 июн. 2009 г., 11:52
Да, да, но есть ли способ сделать его динамичным?

importlib вместо.

Создайте в каталоге 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

так далее. из Foo import * не очень хорошая идея по нескольким причинам, включая конфликт имен и усложнение анализа кода.

 Andrew_151007 мая 2016 г., 04:48
__import__ не для общего использования, он используетсяinterpreter, используйтеimportlib.import_module() вместо.
 Evan Fosmark30 июн. 2009 г., 03:41
Не плохо, но не забывайте, что вы также можете импортировать файлы .pyc и .pyo.
 Alex V.20 июл. 2014 г., 22:46
Добавлятьdel os, слишко
 Lennart Regebro08 мар. 2015 г., 21:14
Это было бы бессмысленно.
 freeforall tousez27 авг. 2014 г., 00:30
ТБХ, я нахожу__import__ хак, я думаю, что было бы лучше добавить имена к__all__ а потом поставьfrom . import * внизу скрипта
Python, включите все файлы в каталоге:

которые просто не могут заставить его работать, которым нужны руки.

Создайте папку / home / el / foo и создайте файлmain.py under / 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

Пример Анурага с парой исправлений:

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 answer с предлагаемыми улучшениями!

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import os
import glob

all_list = list()
for f in glob..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  
Решение Вопроса

Список всех питонов .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')]
 Anurag Uniyal05 мар. 2012 г., 04:26
@ NiallDouglas этот ответ для конкретного вопроса, который задал OP, у него не было zip-файла, и pyc-файлы можно было легко включить, и вы тоже забыли .pyd или .so libs и т. Д.
 Pykler28 февр. 2013 г., 22:12
Единственное, что я хотел бы добавить, этоif not os.path.basename(f).startswith('_') или, по крайней мере,if not f.endswith('__init__.py') до конца понимания списка
 MestreLion05 нояб. 2013 г., 15:51
Чтобы сделать его более надежным, также убедитесь, чтоos.path.isfile(f) являетсяTrue. Это отфильтровывает битые символические ссылки и каталоги, такие какsomedir.py/ (я согласен, но все же ...)
 Evan Fosmark30 июн. 2009 г., 03:29
В основном, чтобы я мог перетаскивать файлы python в каталог без дальнейшей настройки, чтобы они выполнялись скриптом, выполняющимся где-то еще.
 ostrokach08 мая 2016 г., 17:21
Добавлятьfrom . import * после настройки__all__ если вы хотите, чтобы субмодули были доступны с помощью. (например, какmodule.submodule1, module.submodule2, так далее.)

поэтому я написал пакет под названием 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.

Найл

 kanzure05 февр. 2013 г., 09:01
pip не может скачать automodinit, потому что на pypi ничего не загружено.
 Niall Douglas09 февр. 2013 г., 20:28
Спасибо за сообщение об ошибке на GitHub. Я исправил это в v0.13. Найл

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']
 uma mahesh07 мар. 2018 г., 14:14
идеально, именно то, что я ищу

__init__.py определяет__all__.modules - пакеты док говорит

The__init__.py файлы необходимы, чтобы Python рассматривал каталоги как пакеты; это сделано для предотвращения непреднамеренного скрытия действительными модулями каталогов с общим именем, например, строки, которые встречаются позже в пути поиска модулей. В простейшем случае,__init__.py может быть просто пустым файлом, но он также может выполнить код инициализации для пакета или установить__all__ переменная, описанная позже.

...

Единственное решение для автора пакета - предоставить явный индекс пакета. В операторе импорта используется следующее соглашение: если @ паке__init__.py code определяет список с именем__all__, это список имен модулей, которые должны быть импортированы, когда встречается импорт из пакета *. Автор пакета должен обновлять этот список после выпуска новой версии пакета. Авторы пакета могут также принять решение не поддерживать его, если они не видят использования для импорта * из своего пакета. Например, файлsounds/effects/__init__.py может содержать следующий код:

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

Это будет означать, чтоfrom sound.effects import * импортирует три названных субмодуля звукового пакета.

Просто импортируйте их с помощью 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
 Jeppe28 окт. 2018 г., 13:24
Где определено pyfile_extes?
 Cheney31 окт. 2018 г., 11:19
извините, что пропустил это, теперь исправлено. Это расширение файла Python, который вы хотите импортировать, обычно простоpy

я считаю, что нехакерский способ (например, не обрабатывать пути к файлам напрямую) заключается в следующем:

создать пустое__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'>
 Niall Douglas05 мар. 2012 г., 22:00
Еще одна вещь: приведенный выше пример не проверяет sys.modules, чтобы увидеть, загружен ли модуль уже. Без этой проверки вышесказанное загрузит модуль второй раз:)
 Alex Dupuy02 мая 2013 г., 08:37
Когда я запускаю load_all_modules_from_dir ('Foo / bar') с вашим кодом, я получаю "RuntimeWarning: родительский модуль 'Foo / bar' не найден при обработке абсолютного импорта" - чтобы подавить это, я должен установить full_package_name = '.'. Join (dirname.split (os.path.sep) + package_name]), а также импорт Foo.bar
 Luca Invernizzi01 сент. 2012 г., 03:45
Спасибо, теперь это исправлено
 Niall Douglas05 мар. 2012 г., 03:26
Это правильный путь к правильному ответу - он обрабатывает ZIP-архивы, но не пишетв это ни импорт. См. Automodinit ниже.
 Artfunkel04 нояб. 2016 г., 10:16
ТеRuntimeWarning сообщений также можно избежать, вообще не используя full_package_name:importer.find_module(package_name).load_module(package_name).

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())

ам делать именно то, что вы хотите, если у вас есть__init__.py файл в каталоге.__init__.py файл может быть пустым.

Я создал модуль для этого, который не зависит от__init__.py (или любой другой вспомогательный файл) и заставляет меня печатать только следующие две строки:

import importdir
importdir.do("Foo", globals())

Не стесняйтесь повторно использовать или внести свой вклад:http: //gitlab.com/aurelien-lourot/importdi

Ваш ответ на вопрос