Как правильно упаковать набор вызываемых python скриптов или модулей - PullRequest
4 голосов
/ 30 марта 2020

Я довольно долго искал net, но, похоже, не могу понять, как я могу распространять свои python сценарии для моего конечного пользователя.

Я использовал свои сценарии в командной строке, используя эту команду python samplemodule.py "args1"

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

Мои сценарии работают, когда все они находятся в каталоге root проекта, но все рушится, когда я пытаюсь их упаковать и поместить в подкаталоги.

Примером этого является то, что я не могу сейчас запустить свои сценарии, поскольку при импорте модуля из подкаталога data произошла ошибка.

Это структура моего проекта.

MyProject
    \formatter
      __init__.py
      __main__.py
      formatter.py
      addfilename.py
      addscrapertype.py
     ...\data
         __init__.py
         helper.py
     csv_formatter.py
     setup.py

Файл csv_formatter.py - это просто оболочка для вызова formatter.main.

Обновление: теперь я смог сгенерировать пакет tar.gz, но пакет не был вызывается при установке на мою машину.

Это setup.py:

import setuptools

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

setuptools.setup(
    name="formatter",
    version="1.0.1",
    author="My Name",
    author_email="sample@email.com",
    description="A package for cleaning and reformatting csv data",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/RhaEL012/Python-Scripts",
    packages=["formatter"],
    include_package_data=True,
    package_data={
    # If any package contains *.txt or *.rst files, include them:
        "": ["*.csv", "*.rst", "*.txt"],
    },
    entry_points={
         "console_scripts": [
            "formatter=formatter.formatter:main"
        ]
    },
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
    install_requires=[
        "pandas"
    ]
)

Теперь, после установки пакета на компьютер, я не смог вызвать модуль, и это приводит к ошибке:

Z:\>addfilename "C:\Users\Username\Desktop\Python Scripts\"

Error Message

Обновление: я пытаюсь установить setup.py в виртуальной среде, просто чтобы увидеть, откуда исходит ошибка.

Я устанавливаю его, затем получаю следующую ошибку: FileNotFoundError: [Errno 2] no such file or directory: 'README.md'

Я пытаюсь включить README.md в MANIFEST.in, но все равно не повезло. Поэтому я пытаюсь сделать это строкой, чтобы посмотреть, будет ли установка продолжена.

Установка продолжается, но опять же, я сталкиваюсь с ошибкой, которая говорит, что package directory 'formatter' does not exist

Ответы [ 3 ]

3 голосов
/ 03 апреля 2020

Поскольку я не могу просмотреть ваши указанные c файлы, я просто объясню, как я обычно решаю эту проблему.

Так я обычно настраиваю инструменты интерфейса командной строки (cli). Папка проекта выглядит следующим образом:

Projectname
├── modulename
│   ├── __init__.py # this one is empty in this example
│   ├── cli
│   │   ├── __init__.py # this is the __init__.py that I refer to hereafter
│   ├── other_subfolder_with_scripts
├── setup.py

Где все функции находятся в папке и подпапках modulename. В моем __init__.py у меня есть:

def main():
    # perform the things that need to be done 
    # also all imports are within the function call
    print('doing the stuff I should be doing')

, но я думаю, что вы также можете импортировать то, что вы хотите, в __init__.py и по-прежнему ссылаться на него, как я делаю в setup.py. В setup.py у нас есть:

import setuptools

setuptools.setup(
    name='modulename',
    version='0.0.0',
    author='author_name',
    packages=setuptools.find_packages(),
    entry_points={
        'console_scripts': ['do_main_thing=modulename.cli:main'] # so this directly refers to a function available in __init__.py
        },
)

Теперь установите пакет с pip install "path to where setup.py is" Тогда, если он установлен, вы можете позвонить:

do_main_thing
>>> doing the stuff I should be doing

Для документации, которую я использую: https://setuptools.readthedocs.io/en/latest/.

Я рекомендую начать с этого и постепенно добавлять нужные вам функции. Затем шаг за шагом решите свои проблемы, например, добавив README.md et c.

0 голосов
/ 08 апреля 2020

Я не уверен, что это полезно, но обычно я упаковываю свои python сценарии, используя пакет wheel:

pip install wheel
python setup.py sdist bdist_wheel

После этих двух команд пакет whl создается в 'dist' папку, которую вы можете затем загрузить в PyPi и загрузить / установить оттуда, или вы можете установить ее в автономном режиме с помощью "pip install $ {PackageName} .py"

Вот полезное руководство пользователя на всякий случай, если есть что-то еще, что я не объяснил:

https://packaging.python.org/tutorials/packaging-projects/

0 голосов
/ 08 апреля 2020

Я не согласен с другим ответом. Вы не должны запускать сценарии в __init__.py, а в __main__.py.

Projectfolder
├── formatter
│   ├── __init__.py
│   ├── cli
│   │   ├── __init__.py # Import your class module here
│   │   ├── __main__.py # Call your class module here, using __name__ == "__main__"
│   │   ├── your_class_module.py
├── setup.py

Если вы не хотите предоставлять файл readme, просто удалите этот код и введите описание вручную.

Я использую https://setuptools.readthedocs.io/en/latest/setuptools.html#find -namespace-packages вместо ручной установки пакетов.

Теперь вы можете установить пакет, просто запустив pip install ./, как вы делали раньше.

После того, как вы сделали это, запустите: python -m formatter.cli arguments. Он запускает файл __main__.py, который вы создали в папке CLI (или как вы его называли).

Важное замечание о упаковочных модулях заключается в том, что вам необходимо использовать относительный импорт. Например, вы должны использовать from .your_class_module import YourClassModule в этом __init__.py. Если вы хотите импортировать что-либо из соседней папки, вам нужны две точки, from ..helpers import HelperClass.

...