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.