пространства имен python против пакетов: сделать пакет пространством имен по умолчанию - PullRequest
0 голосов
/ 26 ноября 2018

У меня есть проект с всеобъемлющим пространством имен, с пакетами внутри.Вот структура папок:

pypackage
├── pypackage             <-- Source code for use in this project.
|   |
│   ├── bin               <-- Module: Cli entry point into pyproject.
|   |   ├── __init__.py
|   |   └── pypackage.py
|   |
|   └── core              <-- Module: Core functionality.
|       ├── __init__.py
|       └── pypackage.py
|
├── tests             
├── README.md         
└── setup.py          

Довольно просто.Если я хочу импортировать его, я использую:

from pypackage.core import pypackage

, и он прекрасно работает, потому что мой setup.py выглядит так:

from setuptools import setup, find_packages
...
NAME = 'pypackage'
setup(
    name=NAME,
    namespace_packages=[NAME],
    packages=[f'{NAME}.{p}' for p in find_packages(where=NAME)],
    entry_points={
        "console_scripts": [
            f'{NAME} = {NAME}.bin.{NAME}:cli',
        ]
    },
    ...
)

Однако у меня есть устаревший код, который импортирует этот pypackage когда-то это был просто отдельный файл Python.как это:

import pypackage

Так как мне сделать так, чтобы я мог сохранять ту же структуру с пространствами имен и подпакетами, но все же импортировать ее старым способом?Как мне превратить это:

from pypackage.core import pypackage

в это:

import pypackage

Другими словами, как мне псевдоним модуля pypackage.core.pypackage, чтобы он был pypackage для когдаЯ импортирую pypackage во внешний проект?

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Martin Pieters имеет правильную идею, если бы я использовал пакеты, но пакет пространства имен - это вещь setuptools.

Так что это не сработало.После дополнительных исследований я узнал, что нет способа сделать то, что я пытаюсь сделать.Поэтому, если я действительно хочу это сделать, я должен преобразовать все в обычную иерархию пакетов вместо пакета пространств имен, а затем использовать решение Мартина.

Я решил вместо этого изменить старый код, чтобы импортировать его новым способом.

0 голосов
/ 26 ноября 2018

Вы бы добавили «старые» имена в ваш новый пакет, импортировав в пакет верхнего уровня.

Имена, импортированные как глобальные в pypackage/__init__.py, являются атрибутами пакета pypackage.Используйте это для предоставления доступа к «устаревшим» местоположениям:

# add all public names from pypackage.core.pypackage to the top level for
# legacy package use
from .core.pypackage import *

Теперь любой код, который использует import pypackage, может использовать pypackage.foo и pypackage.bar, если в действительности эти объекты были определены в pypackage.core.pypackageвместо этого.

Теперь, поскольку pypackage является setuptools пространством имен package , у вас другая проблема;Пакеты пространства имен предназначены для установки нескольких отдельных дистрибутивов, поэтому пакет верхнего уровня должен быть либо пустой , либо содержать только минимальный файл __init__.py (пакеты пространства имен, созданные с пустыми каталогами, требуют Python 3.3).

Если вы являетесь единственным издателем дистрибутивов, использующих это пространство имен, вы можете немного обмануть здесь и использовать одиночный __init__.py файл в вашем пакете core, который может использовать pkg-util-style __init__.py file с дополнительным импортом, который я использовал выше, но тогда вы не должны использовать файлы __init__.py в других дистрибутивах или требовать, чтобы все они использовали точно такой же __init__.py содержание.Координация здесь является ключевой.

Или вам придется использовать другой подход.Оставьте pypackage как устаревший модуль-обертку и переименуйте новый формат пакета, чтобы использовать новое, другое имя верхнего уровня, которое может находиться рядом со старым модулем.На этом этапе вы можете просто включить устаревший пакет в свой проект напрямую, как дополнительный модуль верхнего уровня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...