Как структурировать пакеты python без повторения имени верхнего уровня для импорта
Я новичок в управлении пакетами python и, несомненно, сделал что-то не так. Мне было предложено создать структуру каталогов следующим образом:
bagoftricks
├── bagoftricks
│ ├── bagoftricks
│ │ ├── __init__.py
│ │ └── bagoftricks.py
│ └── __init__.py
├── README.md
└── setup.py
bagoftricks.py содержит две функции: levenshtein()
и geofind()
.
Я бы назвал их как:
import bagoftricks
x = bagoftricks.levenshtein(arg1,arg2)
Вместо этого я считаю, что должен это сделать:
import bagoftricks
x = bagoftricks.bagoftricks.levenshtein(arg1,arg2)
Есть ли лучший способ организовать мои пакеты в первую очередь без резервирования имен?
UPDATE
Итак, я последовал инструкциям Avichal Badaya ниже и удалил один уровень гнездования. То есть, у меня теперь есть...
bagoftricks
├── bagoftricks
│ ├── __init__.py
│ └── bagoftricks.py
├── README.md
└── setup.py
Однако для вызова этого пакета у меня все еще есть...
from bagoftricks.bagoftricks import geofind()
или
import bagoftricks
затем
>>> bagoftricks.bagoftricks.geofind()
Вместо желаемого....
from bagoftricks import geofind()
или
import bagoftricks
>>> bagoftricks.geofind()
Я не могу удалить этот дополнительный слой вложенности. Когда я попытаюсь, по аналогии, удалить еще один уровень вложенности, чтобы мой модуль был плоским, как:
bagoftricks
├── __init__.py
├── bagoftricks.py
├── README.md
└── setup.py
Я не могу создать пакет вообще...
$ python setup.py build
running build
running build_py
error: package directory 'bagoftricks' does not exist
В чем секрет естественного импорта, например стандартных пакетов, без избыточного импорта имени верхнего уровня?
Ответы
Ответ 1
Первый уровень "bagoftricks" в порядке. Это просто название вашего "проекта", так сказать. У вас есть setup.py и другие файлы, которые сообщают упаковочным системам, что им нужно знать.
Затем вы можете получить код непосредственно в этом модуле или в каталоге src. Вы даже можете дойти до такой структуры:
bagoftricks
├── bagoftricks.py
├── README.md
└── setup.py
Но я бы не рекомендовал это, главным образом потому, что вы захотите реорганизовать вещи позже, и это проще, если у вас уже есть "правильный" пакет. Также большинство людей, инструменты и документы предполагают, что у вас есть пакет, так что это проще.
Таким образом, минимум будет:
bagoftricks
├── bagoftricks
│ └── __init__.py
├── README.md
└── setup.py
С __init__.py
, содержащим функции, которые вы хотите импортировать. Затем вы используете следующие функции:
from bagoftricks import levenshtein, anotherfunction
Как только этот __init__.py
станет слишком большим, вы хотите разбить его на несколько модулей, что даст вам что-то вроде этого:
bagoftricks
├── bagoftricks
│ ├── __init__.py
│ ├── anothermodule.py
│ └── levenshtein.py
├── README.md
└── setup.py
Затем ваш __init__.py
должен импортировать функции из различных модулей:
from bagoftricks.levenshtein import levenshtein
from bagoftricks.anothermodule import anotherfunction
И тогда вы все равно можете использовать их, как и раньше.
Ответ 2
Следуйте следующей структуре:
bagoftricks
── bagoftricks
│ ├── __init__.py
│ └── bagoftricks.py
├── README.md
└── setup.py
а затем вы сможете использовать его как:
from bagoftricks.bagoftricks import levenshtein, geofind
но после внесения изменений в структуру папок выполните: -
pip uninstall <your package name mostly mentioned in setup.py>
и переустановите пакет
тем временем проверьте setup.py
#!/bin/env python
import os.path
from setuptools import setup, find_packages
def current_path(file_name):
return os.abspath(os.path.join(__file__, os.path.pardir, file_name))
setup(
name = 'bagoftricks',
version = '0.1',
include_package_data = True,
packages=find_packages(),
)
У установки могут быть и другие параметры. Надеюсь, это сработает для вас.
Ответ 3
с обновленной структурой, которую вы опубликовали
bagoftricks
├── bagoftricks
│ ├── __init__.py
│ └── bagoftricks.py
├── README.md
└── setup.py
into bagoftricks/__init__.py import all functions that you need
__init__.py
from bagoftricks import geofind, levenshtein
в другую программу, вы можете выполнить следующее:
from bagoftricks import geofind
import bagoftricks; bagoftricks.geofind(); bagoftricks.bagoftriks.geofind()
Заметьте, что вы можете импортировать также wild card
from bagoftricks import *