Два пакета python с одинаковой структурой используют функцию с тем же именем из другого пакета

#python #python-3.x #pip #package #python-packaging

#python #python-3.x #pip #пакет #python-упаковка

Вопрос:

Я создал 2 пакета с именами A и B. Оба пакета имеют одинаковую структуру, поскольку они делают очень похожие вещи, например, их структура выглядит так:

 A/
  __init__.py
  subpackage1/
    __init__.py
    submodule1.py
  subpackage2/
    __init__.py
    submodule2.py
  setup.py
  README.md
  requirements.txt
  

Они используют одни и те же имена подпакетов, подмодулей и функций. У каждого модуля есть функция main, которая выполняет для меня argparsing и вызывает функцию с этими параметрами. В моем setup.py , Я указал дополнительные точки входа, чтобы я мог вызывать модули из командной строки:

 import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()

with open('requirements.txt') as f:
    requirements = f.readlines() 

setuptools.setup(
    name="A",
    version="0.0.1",
    author="Me",
    author_email="me@myself.com",
    description="Test package",
    long_description=long_description,
    long_description_content_type="text/markdown",
    packages=setuptools.find_packages(),
    entry_points ={
        'console_scripts': [
            'command1 = subpackage1.submodule1:main',
            'command2 = subpackage2.submodule2:main'
        ]
    },
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
    install_requires = requirements
)
  

Когда я устанавливаю пакет в пустой контейнер docker, он работает нормально, и я могу вызывать свои функции с помощью ‘command1’ и ‘command2’ из командной строки.

Как указывалось ранее, пакет B имеет точно такую же setup.py файл, за исключением имени. Если я также установлю ее, пакет A теперь использует точки входа пакета B вместо своих собственных. Это означает, что я вызываю функцию с правильным именем, но из неправильного пакета.

Я хочу, чтобы они были рядом в моем контейнере docker. Как мне настроить свои пакеты, чтобы система могла различать их?

Я установил пакеты через pip с колес, которые я сгенерировал.

Комментарии:

1. Первое впечатление, структура каталогов кажется неправильной: первый красный флаг заключается __init__.py в том, что в том же каталоге не должно быть a setup.py , второй красный флаг заключается в том, что каталоги рядом с setup.py не могут быть подпакетами , они должны быть пакетами верхнего уровня .

2. @sinoroc Я удалил верхний уровень __init__.py (который я фактически добавил из-за разочарования незадолго до публикации tbh). Тот же результат, что и раньше. Спасибо за разъяснение терминологии!

Ответ №1:

Первое впечатление, структура каталогов кажется неправильной: первый красный флаг заключается __init__.py в том, что в том же каталоге не должно быть a setup.py , второй красный флаг заключается в том, что каталоги рядом с setup.py не могут быть подпакетами, они являются пакетами верхнего уровня.

В вашем примере пакеты верхнего уровня находятся subpackage1 и subpackage2 в проекте A , и в проекте B . Таким образом, в обоих случаях после установки импортируемыми элементами являются import subpackage1 and import subpackage2 . Это также означает, что при установке A B пакеты верхнего уровня B перезаписывают те, которые были ранее установлены как часть A (поскольку они имеют точно такое же имя).

Что вы, вероятно, хотите сделать, это добавить каталог a в проект A рядом с its setup.py и переместить оба subpackageN , а также __init__.py в этот a каталог (то же самое в проекте B ). Таким образом, структура каталогов выглядит следующим образом:

 A/
  a/
    __init__.py
    subpackage1/
      __init__.py
      submodule1.py
    subpackage2/
      __init__.py
      submodule2.py
  setup.py
  README.md
  requirements.txt
  

Тогда импорт будет выглядеть следующим образом:

 import a.subpackage1
import b.subpackage1

from a import subpackage2 as subpackagea2
from b import subpackage2 as subpackageb2
  

После этого setup.py файлы должны быть соответствующим образом скорректированы:

 # ...

setuptools.setup(
    # ...
    entry_points ={
        'console_scripts': [
            'commanda1 = a.subpackage1.submodule1:main',
            'commanda2 = a.subpackage2.submodule2:main'
        ]
    },
)
  

Комментарии:

1. Это решило мою проблему. По какой-то причине я полностью пропустил эту опцию при разработке пакета. Спасибо!