MANIFEST.in diabaikan pada "python setup.py install" - tidak ada file data yang diinstal?

91

Inilah skrip setup.py saya yang dipreteli dengan hal-hal non-kode dihapus:

#!/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

Ketika saya menjalankan "python setup.py install sdist", saya mendapatkan file .tar.gz yang bagus dengan folder root "whyteboard-0.41", dengan folder lokal / images / dan whyteboard-help / di dalamnya. Ini juga memiliki skrip whyteboard.py saya yang meluncurkan program saya dari dalam paket sumber whyteboard.

Begitu:

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

Ini mencerminkan sumber program saya, bagaimana segala sesuatunya seharusnya, dan benar.

Namun ketika saya menjalankan "python setup.py install" tidak ada file data saya yang ditulis - hanya paket sumber "whyteboard", dan whyteboard.py ditempatkan di /usr/local/lib/python2.6/dist-packages/ .

Idealnya, saya ingin struktur direktori yang sama seperti yang dibuat dalam file .tar.gz dibuat dalam paket-dist, karena program saya mengharapkan untuk mencari sumber dayanya.

Bagaimana saya bisa mendapatkan "install" untuk membuat struktur direktori ini? Sepertinya file manifes saya diabaikan, sejauh yang saya tahu.

Steven Sproat
sumber

Jawaban:

30

Beberapa catatan selain jawaban Ned (yang menyentuh inti masalah):

Distutils tidak menginstal paket dan modul Python di dalam subdirektori per proyek di dalam site-packages(atau dist-packagesdi Debian / Ubuntu): mereka diinstal langsung ke site-packages, seperti yang Anda lihat. Jadi whyteboard-xxdirektori yang berisi di sdist Anda tidak akan ada di formulir terinstal akhir.

Salah satu implikasi dari hal ini adalah Anda harus berhati-hati dalam menamai Anda data_filesdengan cara yang menjelaskan proyek mereka, karena file / direktori tersebut dipasang langsung ke site-packagesdirektori global , bukan di dalam whyteboarddirektori yang memuatnya.

Atau Anda bisa membuat data Anda package_datadari whyteboardpaket tersebut (yang berarti ia harus tinggal di dalam paket itu, yaitu di sebelah __init__.py), dan kemudian ini bukan masalah.

Terakhir, tidak masuk akal untuk memiliki whyteboard.pymodul py_modulesdan whyteboard/__init__.pypaket packages. Keduanya saling eksklusif, dan jika Anda memiliki keduanya, whyteboard.pymodul akan diabaikan oleh impor demi paket dengan nama yang sama.

Jika whyteboard.pyhanya sebuah skrip, dan tidak dimaksudkan untuk diimpor, maka Anda harus menggunakan opsi skrip untuk itu, dan menghapusnya dari py_modules.

Carl Meyer
sumber
1
Itu sangat disayangkan. Saya tidak suka gagasan memiliki data paket - bagi saya, lebih masuk akal bagi sumber daya tersebut untuk tinggal di luar direktori sumber. Saya juga tidak suka memiliki nama direktori yang diawali dengan nama program (meskipun saya sudah melakukannya untuk file bantuan). Hmm ..
Steven Sproat
68

MANIFEST.inmemberi tahu Distutils file apa yang akan disertakan dalam distribusi sumber tetapi tidak secara langsung memengaruhi file apa yang diinstal. Untuk itu Anda perlu menyertakan file-file yang sesuai di dalam setup.pyfile tersebut, umumnya baik sebagai data paket maupun sebagai file tambahan .

Ned Deily
sumber
Saya mencoba menambahkan daftar data paket tetapi tidak ada file yang saya tentukan digunakan. Saya tidak yakin apakah lokasi file diinstal relatif terhadap keseluruhan instalasi paket. Bagaimanapun, itu masih belum menulis file saya dalam struktur direktori yang benar seperti yang saya harapkan.
Steven Sproat
Dokumentasi yang ditautkan dalam jawaban ini memberi Anda semua informasi yang Anda butuhkan tentang di mana data_files dan package_data diinstal. Jika opsi ini tidak berhasil untuk Anda, perbarui pertanyaan Anda dengan sintaks yang sama persis seperti yang Anda coba, hasil, dan harapan Anda.
Carl Meyer
4
Ini bekerja untuk saya: Menduplikasi entri MANIFEST.in saya di dalam data_packages setup.py membuat semuanya bekerja. Terima kasih Ned - Saya telah gagal memahami hal ini selama bertahun-tahun. Semoga pengalaman distutils / setuptools / distribut saya sekarang lebih masuk akal.
Jonathan Hartley
7
Apakah desain untuk dapat menyertakan file dalam paket yang tidak dapat diinstal ini masuk akal? Kapan itu akan digunakan?
Roger Dahl
29

Saya tidak tahu mengapa MANIFEST.infile saya diabaikan ketika saya berlari python setup.py install- ternyata include_package_data=Truemenyelesaikan masalah. The package_dataopsi tidak benar-benar diperlukan.

Greg
sumber
tangkapan bagus, mengapa include_package_data=Truebukan nilai default?
liang
9

Anda harus menggunakan 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'],
)

Ini sebenarnya tidak menggunakan file MANIFEST untuk melakukan pekerjaan itu, tetapi ini menyertakan semua file yang diperlukan.

Juho Rutila
sumber
Ini berhasil untuk saya dengan setuptools . Saya membangun paket Debian dan saya melihat file glade saya yang tercantum dalam package_datakamus muncul di tempat yang tepat hanya setelah saya menambahkan include_package_data=Tru.
mlt
8

Menjalankan python 2.6.1 di Mac OSX, saya sama sekali tidak beruntung kecuali dengan menggunakan parameter data_files di setup.py. Semuanya dengan MANIFEST.in hanya menghasilkan file yang disertakan dalam paket dist, tetapi tidak pernah diinstal. Saya memeriksa beberapa paket lain dan mereka memang menggunakan data_files untuk menentukan file tambahan.

Saya membuat fungsi singkat untuk membantu menghitung semua file dari pohon direktori di

(target_dir, [daftar file]) format yang diharapkan oleh 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

Sekarang saya bisa memanggil ini di dalam panggilan penyiapan saya:

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

Dan semua yang ada di pohon itu dipasang.

Scott Persinger
sumber
11
Ini bagus, tetapi di mana ia dipasang? Bagi saya, saat menggunakan "pip install", data_files saya masuk ke root virtualenv saya (yaitu direktori tunggal yang dibagikan oleh semua paket virtualenv.) Jika menggunakan "setup.py install", maka data_files saya masuk ke "site- paket / <mypackage> .egg / ". Jika file adalah data yang diperlukan pada saat runtime, maka dalam kedua kasus itu tidak sepele bagi kode saya untuk menemukan file ini, dan tentu saja saya harus mencari kedua direktori saat runtime. Jika file tersebut adalah file LISENSI saya, maka dalam kasus apa pun itu tidak sepele bagi pengguna saya untuk mendapatkan dari sumber saya ke LISENSI. Bingung.
Jonathan Hartley
4

Minimal contoh runnable yang diterbitkan

Poin utama: hanya MANIFEST.inbekerja untuk saya, package_datatidak.

Diuji pada Ubuntu 19.10, Python 3.7.5, wheel == 0.32.3, setuptools == 41.1.0, twine == 3.1.1.

Bagaimana pengguna akhir menggunakan paket dari https://pypi.org/project/python-sample-package-with-data/ :

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

Output yang diharapkan:

hello data

Bagaimana pengelola mempublikasikannya:

# 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

File sebenarnya:

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='[email protected]',
    packages=find_packages(),
    include_package_data=True,
    scripts=['python-sample-package-with-data'],
)

Bibliografi:

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber