Python olmayan dosyaları setup.py ile dahil etme


201

setup.pyKodun bir parçası olmayan bir dosyayı nasıl ekleyebilirim? (Özellikle, bir lisans dosyasıdır, ancak başka bir şey olabilir.)

Dosyanın konumunu kontrol edebilmek istiyorum. Özgün kaynak klasöründe, dosya paketin kök dizinindedir. (yani en üstteki ile aynı seviyede __init__.py.) İşletim sisteminden bağımsız olarak paket kurulduğunda tam olarak orada kalmasını istiyorum. Bunu nasıl yaparım?


bunu şu anda nasıl yapıyorsun? önceki sorunuz lisans dosyasını nasıl ekleyeceğinizi bildiğinizi gösteriyor, bu nedenle "çalışmayan" kodunuz nedir?
09:22

2
data_files = [('', ['lgpl2.1_license.txt',]),]Python26 klasörüne koyar.
Ram Rachum

Bazı olumsuz geri bildirimlerden sonra, sorunuzu tekrar okudum ve eksik olduğumu fark ettim. Sorunuza, herhangi bir ek modül (setuptools veya dağıtma gibi) gerektirmeyen, gayretsiz bir çözüm sunmak için cevabımı güncelledim.
Evan Plaice

Teşekkürler Evan. Ancak, çok yaygın olduğu için setuptools'u kullanmakla mükemmelim.
Ram Rachum

Yanıtlar:


225

Muhtemelen bunu yapmanın en iyi yolu setuptools package_datadirektifi kullanmaktır . Bu, yerine setuptools(veya distribute) kullanmak anlamına gelir distutils, ancak bu çok sorunsuz bir "yükseltme" dir.

İşte tam (ama denenmemiş) bir örnek:

from setuptools import setup, find_packages

setup(
    name='your_project_name',
    version='0.1',
    description='A description.',
    packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']),
    package_data={'': ['license.txt']},
    include_package_data=True,
    install_requires=[],
)

Burada kritik olan belirli satırlara dikkat edin:

package_data={'': ['license.txt']},
include_package_data=True,

package_databir dictdesen listesine paket isimleri (boş = tüm paketler) (globs içerebilir) arasında. Örneğin, yalnızca paketinizdeki dosyaları belirtmek istiyorsanız, bunu da yapabilirsiniz:

package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}

Burada çözüm kesinlikle değil sizin olmayan adlandırmak pybir dosya .pyuzantısı.

Daha fazla bilgi için Ian Bicking'ın sunumuna bakın .

GÜNCELLEME: Başka [Daha İyi] Yaklaşım

Sadece kaynak dağıtımının ( sdist) içeriğini kontrol etmek ve paketin dışında dosyalara (örneğin üst düzey dizin) sahip olmak istiyorsanız iyi çalışan başka bir yaklaşım da MANIFEST.indosya eklemektir . Bu dosyanın biçimi için Python belgelerine bakın .

Bu yanıtı yazdığından beri MANIFEST.in, kaynak dağıtımınızın ( tar.gz) ihtiyacınız olan dosyalara sahip olduğundan emin olmak için kullanmanın genellikle daha az sinir bozucu bir yaklaşım olduğunu gördüm .

Örneğin, requirements.txtüst düzeyden eklemek istiyorsanız , üst düzey "veri" dizinini özyineli olarak ekleyin:

include requirements.txt
recursive-include data *

Bununla birlikte, bu dosyaların yükleme sırasında site paketleri içindeki paketin klasörüne kopyalanması include_package_data=Trueiçin, setup()işleve sağlamanız gerekir . Daha fazla bilgi için bkz. Kod Dışı Dosyalar Ekleme .


5
package_data, Python 2.3'ten bu yana salt dağıtım dosyaları kurulum komut dosyaları için de kullanılabilir.
Éric Araujo

15
Bu cevap mantıklı görünüyor, ama benim için çalışmıyor. Package_data çok güvenilir olmadığından (sdist'e dosya eklemek ve bunları ayrı adımlar olarak yüklemek için MANIFEST.in ve setup.py koordinasyonunu gerektirir) ve bu yanıt notlarının yazarı "test edilmez", herkes yoksa onlar için işe yarayıp yaramadığını doğrulayın? LICENSE dosyam sdist'e dahil edildi, ancak "python setup.py install" ne de "pip install Package" ı çalıştırdığımda yüklenmiyor
Jonathan Hartley

11
Ian Bicking'ın sunumu, yalnızca paket içindeki dosyalar için paket verilerinin nasıl yükleneceğini gösterir. LICENSE dosyam projemin en üst düzeyinde, yani herhangi bir pakette değil. Yine de package_data kullanabilir miyim? Veri_dosyalarını kullanmak başlangıç ​​değildir, çünkü dosyaları sistem çapında bir konuma getirir. projemle ilişkili değil ve durumu daha da kötüleştirmek için konum, aynı sdist'ten "setup.py install" veya "pip install" komutunu çalıştırmamıza bağlı olarak değişir.
Jonathan Hartley

8
Benim için çalışma nedeninin dosyanın herhangi bir paket içinde bulunmaması olduğunu tahmin ediyorum - bu deponun en üst düzeyinde bir LICENSE dosyası ve bu nedenle 'package_data' kullanılarak kurulamaz
Jonathan Hartley

7
Bu cevap benim için işe yaramıyor. Ek dosyalar tarball'a
konulmuyor

44

Açıkladığınız şeyi başarmak için iki adım atılacak ...

  • Dosyanın kaynak tarball'a eklenmesi gerekiyor
  • veri dosyasını kaynak yola yüklemek için setup.py dosyasının değiştirilmesi gerekir

Adım 1: Dosyayı kaynak tarball'a eklemek için MANIFEST'e ekleyin

Setup.py dosyasını içeren klasörde bir MANIFEST şablonu oluşturun

MANIFEST temel olarak kaynak tarball'a dahil edilecek tüm dosyaların listesini içeren bir metin dosyasıdır.

Projem için MANIFEST şöyle:

  • CHANGELOG.txt
  • INSTALL.txt
  • License.txt
  • pypreprocessor.py
  • README.txt
  • setup.py
  • test.py
  • todo.txt

Not: sdist bazı dosyaları otomatik olarak eklese de , ne yaptığını ve yapmadığını tahmin etmek yerine onları açıkça emin olmak için belirtmeyi tercih ederim.

Adım 2: Veri dosyasını kaynak klasöre yüklemek için setup.py dosyasını değiştirin

Kaynak yükleme klasörüne bir veri dosyası (LICENSE.txt) eklemek istediğinizden, veri yükleme yolunu kaynak yükleme yoluyla eşleşecek şekilde değiştirmeniz gerekir. Varsayılan olarak, veri dosyaları kaynak dosyalardan farklı bir konuma yüklendiğinden bu gereklidir.

Veri yükleme dizinini kaynak yükleme dizinine uyacak şekilde değiştirmek için ...

Install dir bilgilerini aşağıdaki noktalardan distutils'den alın:

from distutils.command.install import INSTALL_SCHEMES

Veri yükleme dizinini kaynak yükleme dizinine uyacak şekilde değiştirin:

for scheme in INSTALL_SCHEMES.values():
    scheme['data'] = scheme['purelib']

Ve veri dosyasını ve konumunu setup () öğesine ekleyin:

data_files=[('', ['LICENSE.txt'])]

Not: Yukarıdaki adımlar, herhangi bir uzantı kitaplığı gerektirmeden tam olarak standart bir şekilde açıkladığınız işlemi gerçekleştirmelidir.


10
MANIFEST yalnızca kaynak tarball'da bulunan dosyaları kontrol eder (sdist tarafından üretilir). Orada listelenen dosyalar yüklenmeyecek.
David Cournapeau

@David İlk yaklaşımımda ne kadar uzakta olduğumu fark etmedim. Başka üçüncü taraf kütüphanelere ihtiyaç duymadan sorunun ne istediğini başarmak için cevabı güncelledim.
Evan Plaice

3
@ Éric Bunun belirli bir nedeni var mı? ve çalışmak için üçüncü taraf paketleri (setup_tools gibi) gerektirmeyen uygun bir yükleyici alternatifiniz var mı? Kurma araçlarını seçtim çünkü python'un vanilya kurulumuna dahil edildi ve PYPI için modüller inşa ediyordum. Şimdi distutils2 kullanarak bunu yapmak için daha iyi bir yolu olmalı ama ben bir süredir python dokunmadım bu yüzden nasıl bilmiyorum. Distutils2 hakkında bilgili olduğunuzu düşündüğünüz için, uygun bir distutils2 alternatifine sahip olmamızın geri kalanının fayda sağlayacağını düşünüyorum.
Evan Plaice

6
Diğer iş parçacıklarında belirtildiği gibi package_datadosya pakette değilse çalışmaz.
Gringo Suave

2
@ ÉricAraujo: Bu çözümü kullanmak başka bir yol olmadığı için kötü bir fikir değil. Kötü bir tasarımdır - bu doğru. Ama hiçbir zaman değişmeyecek fiili genel API'dır, çünkü birçok şeyi kıracaktır. Diyelim ki distutils2 daha iyi önerilen yollar sağlayacaktır.
anatoly techtonik


8

2019'dur ve işleyen şey - burada ve orada tavsiyeye rağmen, yarı yolda belgelediğim internette bulduğum şey setuptools_scm, seçenek olarak geçti setuptools.setup. Bu, tekerlek paketine git veya başka bir şekilde VCS'nizde sürümlendirilmiş veri dosyalarını içerecek ve bu dosyaları getirmek için git deposundan "pip install" yapacaktır.

Bu iki satırı "setup.py" deki kurulum çağrısına ekledim. Ek yükleme veya içe aktarma gerekmez:

    setup_requires=['setuptools_scm'],
    include_package_data=True,

El ile package_data veya MANIFEST.in dosyasında listelemeye gerek yok - eğer sürümlendirilmişse pakete dahil edilir. "Setuptools_scm" üzerindeki dokümanlar, yürütme konumundan sürüm numarası oluşturmaya vurgu yapar ve veri dosyalarını eklemenin gerçekten önemli bölümünü göz ardı eder. (Ara tekerlek dosyam "* 0.2.2.dev45 + g3495a1f" olarak adlandırılırsa veya yazdığım "0.3.0dev0" sabit kodlu sürüm numarasını kullanırsa daha az umursamıyorum - ancak program için önemli dosyaları bırakarak geride çalışmak biraz önemli)


8

Adım 1:MANIFEST.in Setup.py ile aynı klasörde bir dosya oluşturun

2.Adım: Eklemek istediğiniz dosyaların göreceli yolunu ekleyinMANIFEST.in

include README.rst
include docs/*.txt
include funniest/data.json

3. Adım: set include_package_data=Trueiçinde setup()işlevi site pakete bu dosyaları kopyalamak için

Referans burada.


7

Sorulardan birine yorum yapmak istedim ama bunu yapmak için yeterli itibarım yok.

İşte benim için işe yarayan şey (dokümanlara başvurduktan sonra ortaya çıktı):

package_data={
    'mypkg': ['../*.txt']
},

include_package_data: False

Son satır, garip bir şekilde, benim için de çok önemliydi (bu anahtar kelime argümanını da atlayabilirsiniz - aynı şekilde çalışır).

Bunun yaptığı, üst düzey veya kök dizininizdeki tüm metin dosyalarını ( mypkgdağıtmak istediğiniz paketten bir seviye yukarı) kopyalamasıdır .

Bu yardımcı olur umarım!


Bir tane yaratmak zorunda kalmamanın bir yolunu arıyordum MANIFEST.in, bu benim için çalıştı. Son satır da benim için çok önemliydi. Çizgileriminclude_package_data=False, package_data={ "": ["../CHANGELOG.md"] },
Mendhak

5

Kurulum altında setup.py'de (:

setup(
   name = 'foo library'
   ...
  package_data={
   'foolibrary.folderA': ['*'],     # All files from folder A
   'foolibrary.folderB': ['*.txt']  #All text files from folder B
   },

1
Bu aslında OP'nin amacına ulaşmak için hiçbir şey yapmaz. İnstall komutunun kendisini değiştirmediğiniz sürece, yazdığınız her package_dataşeyin ne üzerinde etkisi setup.py installolmaz. Bu dosyalar paket dizini altında değilse, genellikle kaçınmak istediğiniz bir şeydir.
wvxvw

3

İşte benim için çalışan daha basit bir cevap.

İlk olarak, bir Python Dev'in yukarıdaki yorumu uyarınca, setuptools gerekli değildir:

package_data is also available to pure distutils setup scripts 
since 2.3.  Éric Araujo

Bu harika çünkü paketinize bir kurulum araçları gereksinimi koymak, onu da yüklemeniz gerekeceği anlamına geliyor. Kısacası:

from distutils.core import setup

setup(
    # ...snip...
    packages          = ['pkgname'],
    package_data      = {'pkgname': ['license.txt']},
)

1
Dizin pkgamemevcut değil şikayet edecek
Anthony Kong

1

Sadece Centos 6'da Python 2.7 ile çalışırken bulduğum bir şeyi takip etmek istedim. Yukarıda belirtildiği gibi package_data veya data_files eklemek benim için işe yaramadı. Python olmayan dosyaları tarball'a koyan, ancak bunları RPM aracılığıyla hedef makineye kurmayan bir MANIFEST.IN ekledim.

Sonunda, setup / setuptools içindeki "seçenekler" i kullanarak dosyaları çözümüme sokabildim. Seçenek dosyaları, setup.py dosyasından spec dosyasının çeşitli bölümlerini değiştirmenize izin verir. Aşağıdaki gibi.

from setuptools import setup


setup(
    name='theProjectName',
    version='1',
    packages=['thePackage'],
    url='',
    license='',
    author='me',
    author_email='me@email.com',
    description='',
    options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}},
)

dosyası - MANIFEST.in:

include license.txt

dosya - filewithinstallcommands:

mkdir -p $RPM_BUILD_ROOT/pathtoinstall/
#this line installs your python files
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
#install license.txt into /pathtoinstall folder
install -m 700 license.txt $RPM_BUILD_ROOT/pathtoinstall/
echo /pathtoinstall/license.txt >> INSTALLED_FILES

0

Bu 2020'de çalışıyor!

Diğerlerinin dediği gibi setup.py dosyanızın bulunduğu yerde "MANIFEST.in" dosyasını oluşturun.

Manifest'te gerekli tüm şeyleri dahil edin / hariç tutun. Sözdizimi konusunda burada dikkatli olun. Örn: kaynak pakete dahil edilecek şablon klasörünüz olduğunu varsayalım.

manifest dosyasında bunu yapın:

recursive-include template *

Yukarıdaki gibi dosyalar / dizinler için dir-name ve desen arasında boşluk bıraktığınızdan emin olun. Bizim gibi bunu yapma.

recursive-include template/* [this won't work]

Diğer seçenek dahil kullanmaktır. Birçok seçenek var. Buraya Manifest.in belgelerine bakın

Ve son önemli adım, bu parametreyi setup.py'ye ekleyin ve gitmekte fayda var!

   setup(
    ...
    include_package_data=True,
    ......
)

Umarım yardımcı olur! Mutlu Kodlama!


-12

Bir çözüm anladım: Ben benim değiştirildi lgpl2.1_license.txtetmek lgpl2.1_license.txt.pyve metin etrafında bazı üç çift tırnak koydu. Şimdi data_filesseçeneği kullanmam ya da herhangi bir mutlak yol belirtmem gerekmiyor. Bunu bir Python modülü yapmak çirkin, biliyorum, ama mutlak yollar belirtmekten daha az çirkin görüyorum.


7
Yayına bakın. Çirkin olmak zorunda değil. Paket üzerinde iyi bir dokümantasyon bulmak zor olduğu için internette iyi bir örnek bulmak zor.
Evan Plaice
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.