Bagaimana cara memasukkan paket data dengan setuptools / mendistribusikan?

135

Saat menggunakan setuptools / distribusikan, saya tidak bisa mendapatkan installer untuk menarik package_datafile apa pun . Semua yang saya baca mengatakan bahwa berikut ini adalah cara yang benar untuk melakukannya. Bisakah seseorang memberi saran?

setup(
   name='myapp',
   packages=find_packages(),
   package_data={
      'myapp': ['data/*.txt'],
   },
   include_package_data=True,
   zip_safe=False,
   install_requires=['distribute'],
)

di mana myapp/data/lokasi file data.

cmcginty
sumber
2
Saya mengalami masalah yang sama ... Menentukan secara manual data_filesmemecahkan masalah. Tapi ini rawan kesalahan dan tidak "terasa benar" bagi saya. Dapatkah seseorang memverifikasi bahwa itu benar - benar perlu untuk menduplikasi konfigurasi pada keduanya package_datadan data_files?
exhuma
github.com/wimglenn/resources-example Menunjukkan struktur proyek setuptools modern, yang dapat dengan benar mengemas file data ke dalam roda dan menggunakan sdists pyproject.toml. Tidak setup.pydiperlukan file.
wim

Jawaban:

289

Saya menyadari bahwa ini adalah pertanyaan lama, tetapi bagi orang-orang yang menemukan jalan mereka di sini melalui Google: package_dataadalah kebohongan yang rendah dan kotor . Ini hanya digunakan ketika membangun paket biner ( python setup.py bdist ...) tetapi tidak ketika membangun paket sumber ( python setup.py sdist ...). Ini, tentu saja, konyol - orang akan berharap bahwa membangun distribusi sumber akan menghasilkan kumpulan file yang dapat dikirim ke orang lain untuk membangun distribusi biner.

Bagaimanapun, menggunakan MANIFEST.inakan berfungsi baik untuk distribusi biner dan sumber.

larsks
sumber
97
Saya telah meneliti masalah ini selama satu jam terakhir dan telah mencoba banyak pendekatan. Seperti yang Anda katakan, package_databekerja untuk bdistdan bukan sdist. Namun , MANIFEST.inbekerja untuk sdist, tetapi tidak untuk bdist! Oleh karena itu, yang terbaik yang saya bisa datang dengan adalah untuk mencakup baik package_datadan MANIFEST.indalam rangka untuk mengakomodasi kedua bdistdan sdist.
Wesley Baugh
7
Saya menemukan yang lain untuk mendukung @WesleyBaugh. Di stackoverflow.com/a/2969087/261718 , gunakan MANIFEST.inuntuk file yang tidak akan Anda instal, seperti dokumentasi, dan package_datauntuk file yang Anda gunakan yang bukan kode Python (seperti gambar atau templat).
Drake Guan
12
Saya menggunakan sdist, dan harus memasukkan keduanya MANIFEST.in dan package_data . Tampaknya MANIFEST.inmengontrol apa yang termasuk dalam distribusi, dan package_data mengontrol apa yang kemudian disalin ke dir site_packages selama instalasi. Yang membingungkan, path dalam MANIFEST.inrelatif ke lokasi setup.py, dan package_datarelatif terhadap paket individu (misalnya modul) root.
Edward Newell
9
"Diubah dalam versi 2.7: Semua file yang cocok dengan package_data akan ditambahkan ke file MANIFEST jika tidak ada template yang disediakan. Lihat Menentukan file yang akan didistribusikan." dari distutils . Jadi, Anda hanya akan melihat perilaku file package_datayang secara otomatis termasuk dalam ZIP jika Anda tidak memiliki file MANIFEST.in yang ada , dan hanya jika Anda menggunakan 2,7+.
Johnus
29
Serius, saya merasa seperti tiket ini adalah sesi terapi kelompok untuk orang-orang yang menggunakan setuptools dan menemukan tempat mengerikan yang mereka temukan dalam hidup.
Matt Joyce
32

Saya baru saja mengalami masalah yang sama. Solusinya, cukup dengan menghapus include_package_data=True.

Setelah membaca di sini , saya menyadari bahwa ini include_package_databertujuan untuk memasukkan file dari kontrol versi , bukan hanya "memasukkan data paket" seperti namanya. Dari dokumen:

File data [dari include_package_data] harus di bawah kendali CVS atau Subversion

...

Jika Anda ingin kontrol lebih halus atas file apa saja yang disertakan (misalnya, jika Anda memiliki file dokumentasi di direktori paket Anda dan ingin mengecualikannya dari instalasi), maka Anda juga dapat menggunakan package_datakata kunci.

Membuang argumen itu untuk memperbaikinya, yang merupakan alasan mengapa argumen ini juga berfungsi ketika Anda beralih ke distutils, karena argumen itu tidak menerima argumen itu.

Joe
sumber
2
Pengalaman saya berbeda, saya punya masalah yang sama tanpa memasukkan include_package_data=Trueentri. Satu-satunya solusi bagi saya adalah menambahkan entri di Manifest seperti yang disarankan di atas. Pikiran Anda saya menggunakan setuptools, mungkin versi Anda berfungsi dengan 'mendistribusikan'?
TimStaley
4
Alasan sebenarnya mengapa menghapus include_package_datapemecahan masalah lebih lanjut dalam teks asli - Jika menggunakan include_package_dataargumen setuptools spesifik , file yang ditentukan oleh package_datatidak akan secara otomatis ditambahkan ke manifes kecuali mereka terdaftar dalam MANIFEST.infile.
Piotr Dobrogost
Apa gunanya package_datamengatur ke daftar yang tidak kosong dan menentukan include_package_data=False? Dan mengapa Anda perlu menentukan file dua kali dalam MANIFEST.indan package_data?
Herbert
21

Mengikuti rekomendasi @ Jo untuk menghapus include_package_data=Truesaluran juga bekerja untuk saya.

Untuk sedikit lebih rumit, saya tidak punya MANIFEST.infile. Saya menggunakan Git dan bukan CVS.

Repositori berbentuk seperti ini:

/myrepo
    - .git/
    - setup.py
    - myproject
        - __init__.py
        - some_mod
            - __init__.py
            - animals.py
            - rocks.py
        - config
            - __init__.py
            - settings.py
            - other_settings.special
            - cool.huh
            - other_settings.xml
        - words
            - __init__.py
            word_set.txt

setup.py:

from setuptools import setup, find_packages
import os.path

setup (
    name='myproject',
    version = "4.19",
    packages = find_packages(),  
    # package_dir={'mypkg': 'src/mypkg'},  # didnt use this.
    package_data = {
        # If any package contains *.txt or *.rst files, include them:
        '': ['*.txt', '*.xml', '*.special', '*.huh'],
    },

#
    # Oddly enough, include_package_data=True prevented package_data from working.
    # include_package_data=True, # Commented out.
    data_files=[
#               ('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
        ('/opt/local/myproject/etc', ['myproject/config/settings.py', 'myproject/config/other_settings.special']),
        ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'cool.huh')]),
#
        ('/opt/local/myproject/etc', [os.path.join('myproject/config', 'other_settings.xml')]),
        ('/opt/local/myproject/data', [os.path.join('myproject/words', 'word_set.txt')]),
    ],

    install_requires=[ 'jsonschema',
        'logging', ],

     entry_points = {
        'console_scripts': [
            # Blah...
        ], },
)

Saya menjalankan python setup.py sdistdistrib sumber (belum mencoba biner).

Dan ketika di dalam lingkungan virtual baru, saya punya myproject-4.19.tar.gz, file, dan saya gunakan

(venv) pip install ~/myproject-4.19.tar.gz
...

Dan selain semuanya yang diinstal ke lingkungan virtual saya site-packages, file data khusus itu diinstal ke /opt/local/myproject/datadan /opt/local/myproject/etc.

HeyWatchThis
sumber
16

include_package_data=True bekerja untukku.

Jika Anda menggunakan git, ingat untuk menyertakan setuptools-gitdi install_requires. Jauh lebih tidak membosankan daripada memiliki Manifestatau memasukkan semua jalan masukpackage_data (dalam kasus saya ini adalah aplikasi Django dengan semua jenis statika)

(disisipkan komentar yang saya buat, seperti k3-rnc sebutkan itu sebenarnya membantu apa adanya)

vincent
sumber
7

Pembaruan : Jawaban ini sudah tua dan informasinya tidak lagi valid. Semua konfigurasi setup.py harus digunakan import setuptools. Saya telah menambahkan jawaban yang lebih lengkap di https://stackoverflow.com/a/49501350/64313


Saya memecahkan masalah ini dengan beralih ke distutils. Sepertinya mendistribusikan sudah usang dan / atau rusak.

from distutils.core import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_data={
      'myapp': ['data/*.txt'],
   },
)
cmcginty
sumber
2
mendistribusikan tidak usang, itu mengganti distutils. Saya tidak tahu mengapa Anda mengalami masalah, tetapi bukan itu alasannya.
agf
1
Itulah tanggapan yang saya dapatkan dari IRC, jadi siapa yang saya percayai? Jika Anda memiliki contoh kerja menggunakan mendistribusikan saya akan sangat menghargai itu.
cmcginty
6
klarifikasi: mendistribusikan dimaksudkan untuk menggantikan alat setup, keduanya dibangun di atas distutil. distutils itu sendiri pada akhirnya akan digantikan oleh paket baru, yang disebut "distutils2" di python2 dan "packaging" di python3
Kevin Horn
1
Beralih ke distutils menyelesaikan masalah saya di mana include_package_data=Truetidak dihormati. Jadi dengan pengaturan itu Anda hanya perlu MANIFEST.in - tidak perlu menduplikasi daftar file Anda dalam package_datapengaturan.
Daniel Sokolowski
4

Pertanyaan kuno namun ... manajemen paket python benar-benar menyisakan banyak yang diinginkan. Jadi saya punya kasus penggunaan menginstal menggunakan pip secara lokal ke direktori yang ditentukan dan terkejut kedua jalur package_data dan data_files tidak berhasil. Saya tidak tertarik untuk menambahkan file lain ke repo jadi saya akhirnya memanfaatkan data_files dan opsi setup.py - install-data; sesuatu seperti ini

pip install . --install-option="--install-data=$PWD/package" -t package  
Mat Baker
sumber
3

Saya memiliki masalah yang sama selama beberapa hari tetapi bahkan utas ini tidak dapat membantu saya karena semuanya membingungkan. Jadi saya melakukan riset dan menemukan solusi berikut:

Pada dasarnya dalam hal ini, Anda harus melakukan:

from setuptools import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_dir={'myapp':'myapp'}, # the one line where all the magic happens
   package_data={
      'myapp': ['data/*.txt'],
   },
)

Jawaban lengkap stackoverflow lainnya di sini

moctarjallo
sumber
Sudah mencoba ini, tapi tetap tidak ada yang disalin.
gerrit
3

Hapus saja garis:

include_package_data=True,

dari skrip pengaturan Anda, dan itu akan berfungsi dengan baik. (Diuji sekarang dengan alat setup terbaru.)

Ian
sumber
Ini gila tetapi bekerja baik dengan sdistdan bdist_wheel, sudahkah Anda memeriksa alasannya?
Szabolcs
1
Saya memang bisa mengkonfirmasi bahwa sdistmengabaikan package_dataketika ini diatur.
Sander Steffann
Pada titik ini sudah berbulan-bulan, tetapi saya sepertinya ingat-ingat menggali kode, tersesat dua kali, mengambil sisir bergigi luar biasa ke dokumentasi, dan mendapatkan kepuasan. Rupanya berbagai skrip sampel berisi flag ini dan itu menyebabkan sakit kepala yang tak ada habisnya.
Ian
1

Menggunakan setup.cfg (setuptools ≥ 30.3.0)

Dimulai dengan setuptools 30.3.0 (dirilis 2016-12-08), Anda dapat menjaga setup.pysangat kecil dan memindahkan konfigurasi ke setup.cfgfile. Dengan pendekatan ini, Anda bisa meletakkan data paket Anda di [options.package_data]bagian:

[options.package_data]
* = *.txt, *.rst
hello = *.msg

Dalam hal ini, Anda setup.pydapat sesingkat:

from setuptools import setup
setup()

Untuk informasi lebih lanjut, lihat mengkonfigurasi pengaturan menggunakan file setup.cfg .

Ada beberapa pembicaraan tentang penghentiansetup.cfg mendukung pyproject.tomlseperti yang diusulkan dalam PEP 518 , tetapi ini masih bersifat sementara pada 2020-02-21.

gerrit
sumber
Jawaban ini lalai menyebutkan file MANIFEST jadi saya pikir itu tidak akan berfungsi dengan sdist. Hanya dengan roda. Anda harus menyebutkan itu.
wim
@wim Saya tidak punya cukup pemahaman tentang MANIFEST, sdist, dan roda untuk menjawab itu. Ini bekerja untuk saya gunakan pip install.
gerrit
Itu karena pip install, untuk versi pip yang cukup modern, pertama-tama akan membangun roda dan kemudian menginstalnya. Namun bagi banyak pengguna pendekatan ini diam-diam akan gagal memasukkan data paket. Lihat jawaban yang diterima dan komentar di bawahnya untuk perincian tentang itu. Menggunakan a setup.cfgsebenarnya hanya cara penulisan yang berbeda dari apa yang sudah dilakukan OP setup.pydalam pertanyaan (dengan melewatkan package_dataargumen kata kunci dalam panggilan ke setup), jadi saya tidak berpikir ini sangat membantu sebagai jawaban untuk pertanyaan ini . Itu sama sekali tidak mengatasi masalah mendasar.
wim