MANIFEST.in ละเว้นใน“ การติดตั้ง python setup.py” - ไม่มีการติดตั้งไฟล์ข้อมูล?


91

นี่คือสคริปต์ 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" โดยมี locale / 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-package เนื่องจากนี่คือวิธีที่โปรแกรมของฉันคาดหวังที่จะค้นหาทรัพยากร

ฉันจะ "ติดตั้ง" เพื่อสร้างโครงสร้างไดเร็กทอรีนี้ได้อย่างไร ดูเหมือนว่าจะไม่สนใจไฟล์ Manifest ของฉันเท่าที่ฉันสามารถบอกได้


คำตอบ:


30

บันทึกบางส่วนนอกเหนือจากคำตอบของ Ned (ซึ่งกระทบกับปัญหาหลัก):

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
ที่โชคร้าย ฉันไม่ชอบแนวคิดเรื่องการมีข้อมูลแพ็คเกจสำหรับฉันแล้วมันสมเหตุสมผลกว่าที่ทรัพยากรเหล่านั้นจะอยู่นอกไดเร็กทอรีต้นทาง ฉันไม่ชอบที่จะต้องมีชื่อไดเร็กทอรีที่นำหน้าด้วยชื่อโปรแกรม (แม้ว่าฉันจะทำเช่นนั้นสำหรับไฟล์วิธีใช้แล้วก็ตาม) อืม ..
Steven Sproat

68

MANIFEST.inบอกความแตกต่างว่าจะรวมไฟล์ใดในการแจกจ่ายต้นทาง แต่ไม่ส่งผลโดยตรงต่อไฟล์ที่ติดตั้ง สำหรับสิ่งที่คุณต้องรวมไฟล์ที่เหมาะสมในsetup.pyไฟล์ทั่วไปไม่ว่าจะเป็นข้อมูลแพคเกจหรือเป็นแฟ้มเพิ่มเติม


ฉันพยายามเพิ่มรายการข้อมูลแพ็กเกจ แต่ไม่มีการใช้ไฟล์ใดที่ฉันระบุ ฉันไม่แน่ใจว่าตำแหน่งของไฟล์ถูกติดตั้งโดยสัมพันธ์กับการติดตั้งโดยรวมของแพ็คเกจหรือไม่ อย่างไรก็ตามมันยังไม่ได้เขียนไฟล์ของฉันในโครงสร้างไดเร็กทอรีที่ถูกต้องที่ฉันคาดไว้
Steven Sproat

เอกสารที่เชื่อมโยงในคำตอบนี้จะให้ข้อมูลทั้งหมดที่คุณต้องการเกี่ยวกับตำแหน่งที่ติดตั้ง data_files และ package_data หากตัวเลือกเหล่านี้ไม่ได้ผลสำหรับคุณโปรดอัปเดตคำถามของคุณด้วยไวยากรณ์ที่คุณได้ลองใช้ผลลัพธ์และสิ่งที่คุณคาดหวัง
Carl Meyer

4
สิ่งนี้ใช้ได้กับฉัน: การทำซ้ำรายการ MANIFEST.in ของฉันภายใน data_packages ของ setup.py ทำให้ทุกอย่างทำงานได้ ขอบคุณเน็ด - ฉันไม่เข้าใจประเด็นนี้มาหลายปีแล้ว หวังว่าตอนนี้ distutils / setuptools / แจกจ่ายประสบการณ์ของฉันจะสมเหตุสมผลมากขึ้น
Jonathan Hartley

7
การออกแบบให้สามารถรวมไฟล์ในแพ็กเกจที่จะไม่ได้รับการติดตั้งนี้เหมาะสมหรือไม่? จะใช้เมื่อใด
Roger Dahl

29

ฉันคิดไม่ออกว่าทำไมMANIFEST.inไฟล์ของฉันถึงถูกละเลยเมื่อฉันวิ่งpython setup.py install- ปรากฎว่าinclude_package_data=Trueแก้ปัญหาได้ package_dataตัวเลือกที่ไม่จำเป็นต้องใช้จริง


จับดีทำไมinclude_package_data=Trueไม่เป็นค่าเริ่มต้น?
liang

9

คุณควรใช้ 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

8

ใช้ python 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" data_files ของฉันจะเข้าสู่รูทของ Virtualenv ของฉัน (เช่นไดเร็กทอรีเดียวที่ใช้ร่วมกันโดยแพ็คเกจของ Virtualenv ทั้งหมด) หากใช้ "setup.py install" ดังนั้น data_files ของฉันจะไปที่ "site- แพ็คเกจ / <mypackage> .egg / ". หากไฟล์เป็นข้อมูลที่ต้องการในรันไทม์ไม่ว่าในกรณีใดรหัสของฉันก็ไม่สำคัญในการค้นหาไฟล์เหล่านี้และแน่นอนว่าฉันต้องค้นหาทั้งสองไดเร็กทอรีที่รันไทม์ หากไฟล์นั้นเป็นไฟล์ LICENSE ของฉันไม่ว่าในกรณีใดก็ไม่สำคัญสำหรับผู้ใช้ของฉันที่ได้รับจากแหล่งที่มาไปยัง LICENSE งง.
Jonathan Hartley

4

ตัวอย่างที่เผยแพร่ได้น้อยที่สุด

ประเด็นสำคัญ: ใช้ได้ผลMANIFEST.inสำหรับฉันเท่านั้นpackage_dataไม่ได้

ทดสอบบน Ubuntu 19.10, Python 3.7.5, wheel == 0.32.3, setuptools == 41.1.0, twine == 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'],
)

บรรณานุกรม:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.