Импортируйте все классы (или функции) во все файлы в папке, как если бы они были все в файле __init__
У меня есть папка с несколькими файлами, содержащими множество разных классов. Все они могут быть в одном большом файле, но для того, чтобы сделать его немного легче читать, я разделил его на несколько файлов в зависимости от того, к каким классам принадлежит.
Я хотел бы импортировать все классы из всех файлов в папку в файл __init__
чтобы я мог импортировать что-либо из папки, не зная, в какой файл он принадлежит.
Пример:
/kitchen
+ __init__.py
+ fridge.py
+ stove.py
+ cupboard.py
Теперь я должен сделать
from kitchen.fridge import milk
Когда я хочу сделать
from kitchen import milk
Эквивалент этого я могу пройти через __init__.py
:
from kitchen.fridge import *
from kitchen.stove import *
from kitchen.cupboard import *
И тогда я могу сделать
from kitchen import milk
Но я бы хотел, чтобы все файлы находились в папке без необходимости явно указывать (чтобы файлы можно было сбрасывать там и затем использовать).
Есть ли способ сделать это?
Ответы
Ответ 1
Это очень плохая идея. Если вы хотите добавить механизм для файлов, которые будут "сбрасываться там и используются", вы, вероятно, захотите разработать схему плагина и явно искать каталог плагинов (-ов).
Как вы обычно это делаете, это перебрать один или несколько каталогов плагинов с помощью os.listdir
или os.walk
, затем для каждого файла Python используйте importlib
(или эквиваленты нижнего уровня от imp
, в Python 2.x), чтобы импортировать его по пути.
Однако, если вы действительно настаиваете на том, чтобы подделывать вещи таким образом внутри пакета, вы можете сделать в основном те же самые трюки в файле __init__.py
, используя os.path.dirname(__file__)
в качестве каталога плагина.
И, если вы действительно настаиваете на том, чтобы сделать эквивалент from foo import *
вместо import foo
по пути, это так же просто или, альтернативно, вы можете использовать execfile
.
Если вы не знаете, как делать эти простые вещи или как их искать в документах... то вам определенно не следует пытаться это делать. Поэтому я не буду приводить пример кода в этом случае.
Ответ 2
Явный лучше, чем неявный. Не делай этого. Вы можете, конечно, взломать что-то вместе, что в какой-то степени автоматизирует импорт. Но это действительно не стоит. Это всего лишь одна дополнительная строка на добавленный файл в __init__.py
и все готово. Простые решения лучше, если вы не получите многого из более сложного, что, конечно же, не так.
Ответ 3
Нет, нет. Кроме того, вы не должны import *
, но в __init__.py
явно. Кстати, этот способ разделения модулей является обычным явлением и хорошей практикой.
import *
допустим, если вы также определяете атрибут __all__
в каждом модуле, но нет никакой реальной выгоды от этого, и он имеет тенденцию нарушать анализаторы кода.
Ответ 4
import os, sys
dir_path = os.path.dirname(os.path.abspath(__file__))
files_in_dir = [f[:-3] for f in os.listdir(dir_path)
if f.endswith('.py') and f != '__init__.py']
for f in files_in_dir:
mod = __import__('.'.join([__name__, f]), fromlist=[f])
to_import = [getattr(mod, x) for x in dir(mod)]
# if isinstance(getattr(mod, x), type)] # if you need classes only
for i in to_import:
try:
setattr(sys.modules[__name__], i.__name__, i)
except AttributeError:
pass