MANIFEST.in проігноровано на “python setup.py install” - файли даних не встановлені?


89

Ось мій зачищений скрипт setup.py із видаленими некодовими матеріалами:

#!/usr/bin/env python

from distutils.core import setup
from whyteboard.misc import meta


setup(
    name = 'Whyteboard',
    version = meta.version,

    packages = ['whyteboard', 'whyteboard.gui', 'whyteboard.lib', 'whyteboard.lib.pubsub',
                'whyteboard.lib.pubsub.core', 'whyteboard.lib.pubsub.utils', 'whyteboard.misc'],

    py_modules = ['whyteboard'],
    scripts = ['whyteboard.py'],
)

MANIFEST.in:

include *.txt
include whyteboard-help/*.*
recursive-include locale *.mo
recursive-include images *.png

Коли я запускаю "python setup.py install sdist", я отримую приємний файл .tar.gz з кореневою папкою "whyteboard-0.41", з моєю локаллю / images / і whyteboard-help / папками всередині. Тут також мій сценарій whyteboard.py, який запускає мою програму зсередини вихідного пакета whyteboard.

Тому:

whyteboard/
 ├── locale/
 ├── images
 ├── whyteboard-help/
 ├── whyteboard/
 │  ├── __init__.py
 │  └── other packages etc
 ├── whyteboard.py
 ├── README
 ├── setup.py
 └── CHANGELOG

Це відображає джерело моєї програми, це те, як все повинно бути, і є правильним.

Однак, коли я запускаю "python setup.py install", жоден з моїх файлів даних не записується - лише вихідний пакет "whyteboard", і whyteboard.py розміщується в /usr/local/lib/python2.6/dist-packages/ .

В ідеалі, я хотів би, щоб та сама структура каталогів, що була створена у файлі .tar.gz, створювалась у пакунках dist, оскільки саме така програма розраховує шукати свої ресурси.

Як я можу отримати "встановити" для створення цієї структури каталогів? Здається, це ігнорує мій файл маніфесту, наскільки я можу судити.


Відповіді:


30

Деякі примітки на додаток до відповіді Неда (яка вражає основну проблему):

Distutils не встановлює пакунки та модулі Python усередині підкаталогу кожного проекту в site-packages(або dist-packagesна Debian / Ubuntu): вони встановлюються безпосередньо в site-packages, як ви вже бачили. Отже, що містить whyteboard-xxкаталог у вашому sdist не буде існувати у остаточно встановленій формі.

Одним із наслідків цього є те, що ви повинні бути обережними, щоб назвати свої data_filesтаким чином, щоб уточнити, до якого проекту вони належать, оскільки ці файли / каталоги встановлюються безпосередньо в глобальний site-packagesкаталог, а не всередині будь-якого whyteboardкаталогу, що містить .

Або ви могли б замість того, щоб зробити дані package_dataпро whyteboardпакеті (що означає , що він повинен жити всередині цього пакета, тобто поряд з необхідними __init__.py), і тоді це не проблема.

Нарешті, не має сенсу мати як whyteboard.pyмодуль, так py_modulesі whyteboard/__init__.pyпакет packages. Ці два варіанти взаємовиключні, і якщо у вас є обидва, whyteboard.pyмодуль буде ігноруватися імпортом на користь однойменного пакета.

Якщо whyteboard.pyце лише скрипт, який не призначений для імпорту, тоді вам слід скористатися опцією сценаріїв для нього та видалити з нього py_modules.


1
Це прикро. Мені не подобається ідея мати дані пакета - для мене більш доцільно, щоб ці ресурси жили поза вихідним каталогом. Також мені не подобається, щоб імена каталогів мали префікс до назви програми (хоча я це вже роблю для файлів довідки). Хм ..
— Стівен Спрот

67

MANIFEST.inповідомляє Distutils, які файли включати до вихідного розподілу, але це безпосередньо не впливає на те, які файли встановлені. Для цього вам потрібно включити відповідні файли у setup.pyфайл, як правило, як дані пакету або як додаткові файли .


Я спробував додати список даних пакету, але жоден із вказаних мною файлів не використовувався. Я не був впевнений, чи було встановлено розташування файлів щодо загальної інсталяції пакету. У будь-якому випадку, мої файли все ще не писались у правильній структурі каталогів, яку я очікував.
— Стівен Спрот,

Документація, на яку посилається ця відповідь, надає всю необхідну інформацію про те, де встановлені data_files та package_data. Якщо ці параметри не працюють для вас, оновіть своє питання з точним синтаксисом, який ви спробували, результатами та тим, що ви очікували.
— Carl Meyer

4
Це працює для мене: копіювання моїх записів MANIFEST.in всередині data_packages setup.py змушує все працювати. Дякую Неде - я роками не розумію цього. Сподіваємось, тепер мої distutils / setuptools / поширюватимуть досвід будуть мати більше сенсу.
— Джонатан Хартлі,

7
Чи має сенс така конструкція можливості включати в пакет файли, які не встановлюватимуться? Коли його використовувати?
— Роджер Даль

27

Я не міг зрозуміти, чому MANIFEST.inпри запуску мій файл ігнорувався python setup.py install- виявляється, include_package_data=Trueвирішує проблему. package_dataВаріант на насправді не потрібно.


хороший улов, чому include_package_data=Trueне значення за замовчуванням?
— лян

8

Запуск пітона 2.6.1 на Mac OSX, у мене не було абсолютно ніякої удачі за винятком використання data_files параметра в setup.py. Все, що було з MANIFEST.in, просто призвело до того, що файли були включені до пакету dist, але так і не були встановлені. Я перевірив деякі інші пакети, і вони справді використовували data_files для вказівки додаткових файлів.

Я створив коротку функцію, яка допоможе перелічити всі файли з дерева каталогів у

(target_dir, [список файлів]) формат, який очікують data_files:

def gen_data_files(*dirs):
    results = []

    for src_dir in dirs:
        for root,dirs,files in os.walk(src_dir):
            results.append((root, map(lambda f:root + "/" + f, files)))
    return results

Тепер я можу просто викликати це всередині мого виклику налаштування:

setup(... data_files = gen_data_files("docs", "lib") ...

І все на цих деревах встановлюється.


11
Це чудово, але куди це встановлюється? Для мене, коли я використовую "pip install", мої файли даних потрапляють у кореневу частину мого virtualenv (тобто єдиний каталог, спільний для всіх пакетів virtualenv.) Якщо використовується "setup.py install", то мої data_files переходять у "site- пакети / <мій пакет> .egg / ". Якщо файли є даними, необхідними під час виконання, то в жодному випадку не тривіально для мого коду знаходити ці файли, і, звичайно, мені доводиться шукати обидва каталоги під час виконання. Якщо файли - це мій файл ЛІЦЕНЗІЇ, то в жодному випадку це не є тривіальним для моїх користувачів переходом від мого джерела до ЛІЦЕНЗІЇ. Спантеличений.
— Джонатан Хартлі

8

Вам слід використовувати setuptools:

#!/usr/bin/env python

from setuptools import setup, find_packages
from whyteboard.misc import meta


setup(
  name = 'Whyteboard',
  version = meta.version,

  packages = find_packages(),
  include_package_data=True,

  py_modules = ['whyteboard'],
  scripts = ['whyteboard.py'],
)

Насправді для роботи не використовується файл MANIFEST, але він включає всі необхідні файли.


Це спрацювало для мене з setuptools . Я будую пакет Debian і бачу, що мої файли glade, перелічені у package_dataсловнику, з'являються в потрібному місці лише після того, як я додав include_package_data=Tru.
— mlt

3

Мінімальний опублікований приклад для запуску

Ключовий винос: MANIFEST.inпрацював лише у мене, package_dataні.

Перевірено на Ubuntu 19.10, Python 3.7.5, колесо == 0.32.3, setuptools == 41.1.0, шпагат == 3.1.1.

Як кінцеві користувачі використовують пакет із https://pypi.org/project/python-sample-package-with-data/ :

python3 -m pip install --user python-sample-package-with-data
python-sample-package-with-data

Очікуваний результат:

hello data

Як публікують це супровідники:

# One time setup.
python3 -m pip install --user setuptools wheel twine

# Every time you want to publish.
python setup.py sdist bdist_wheel
twine upload dist/*
rm -rf build dist *.egg-info

Фактичні файли:

MANIFEST.in

# Or else pip install cannot find README.md on the setup.py under certain conditions.
include README.md

# This actually adds the data file.
include python_sample_package_with_data/mydata.txt

python-sample-package-with-data

#!/usr/bin/env python3

import python_sample_package_with_data

print(python_sample_package_with_data.get_data(), end='')

python_sample_package_with_data / __ init__.py

try:
    import importlib.resources as importlib_resources
except ImportError:
    # In PY<3.7 fall-back to backported `importlib_resources`.
    import importlib_resources

def get_data():
    return importlib_resources.read_text(__name__, 'mydata.txt')

python_sample_package_with_data / mydata.txt

hello data

setup.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from setuptools import setup, find_packages

from os import path
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md')) as f:
    long_description = f.read()

setup(
    name='python-sample-package-with-data',
    version='0.0.3',
    description='My short description',
    long_description=long_description,
    long_description_content_type='text/markdown',
    url='https://github.com/cirosantilli/python-sample-package-with-data',
    author='Ciro Santilli',
    author_email='ciro.santilli.contact@gmail.com',
    packages=find_packages(),
    include_package_data=True,
    scripts=['python-sample-package-with-data'],
)

Бібліографія:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.