Jak dołączyć dane pakietu do setuptools / Distribute?

135

Podczas korzystania z setuptools / Distribute nie mogę pobrać instalatora żadnych package_dataplików. Wszystko, co przeczytałem, mówi, że następujący sposób jest właściwy. Czy ktoś może doradzić?

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

gdzie myapp/data/jest lokalizacja plików danych.

cmcginty
źródło
2
Mam ten sam problem ... Ręczne określenie data_filesrozwiązania problemu. Ale jest to podatne na błędy i nie „wydaje mi się właściwe”. Czy ktoś może sprawdzić, czy naprawdę konieczne jest zduplikowanie konfiguracji w obu package_datai data_files?
exhuma
github.com/wimglenn/resources-example Pokazuje nowoczesną strukturę projektu setuptools, która może poprawnie pakować pliki danych do kół i sdists przy użyciu pyproject.toml. Nie jest setup.pywymagany plik.
wim

Odpowiedzi:

289

Zdaję sobie sprawę, że to stare pytanie, ale dla osób, które trafiają tutaj przez Google: package_datato proste, brudne kłamstwo . Jest używany tylko podczas budowania pakietów binarnych ( python setup.py bdist ...), ale nie podczas budowania pakietów źródłowych ( python setup.py sdist ...). Jest to oczywiście absurdalne - można by się spodziewać, że zbudowanie dystrybucji źródłowej zaowocuje kolekcją plików, które można wysłać komuś innemu w celu zbudowania dystrybucji binarnej.

W każdym razie użycie MANIFEST.inbędzie działać zarówno dla dystrybucji binarnych, jak i źródłowych.

larsks
źródło
97
Badałem ten problem przez ostatnią godzinę i próbowałem wielu podejść. Jak mówisz, package_datadziała dla bdisti nie sdist. Jednakże , MANIFEST.inpracuje sdist, ale nie za bdist! Dlatego najlepsze, co udało mi się wymyślić, to uwzględnienie obu package_datai MANIFEST.inaby pomieścić zarówno bdisti sdist.
Wesley Baugh
7
Znalazłem innego, który wspiera @WesleyBaugh. Na stackoverflow.com/a/2969087/261718 , użyj MANIFEST.indla plików, których nie chcesz zainstalować, takich jak dokumentacja, oraz package_datadla plików, których używasz, które nie są kodem Pythona (jak obraz lub szablon).
Drake Guan
12
Używam sdist i musiałem uwzględnić zarówno MANIFEST.in i package_data . Wygląda na to, że MANIFEST.inkontroluje to, co jest zawarte w dystrybucji, a package_data kontroluje to, co jest później kopiowane do katalogu site_packages podczas instalacji. Mylące, ścieżki w MANIFEST.insą względne w stosunku do lokalizacji setup.py i package_datasą względne w stosunku do katalogu głównego poszczególnych pakietów (np. Modułów).
Edward Newell,
9
„Zmieniono w wersji 2.7: wszystkie pliki, które pasują do danych_pakietu, zostaną dodane do pliku MANIFEST, jeśli nie zostanie dostarczony żaden szablon. Zobacz Określanie plików do dystrybucji.” z destylatów . Tak więc, zobaczysz zachowanie plików package_dataautomatycznie dołączanych do ZIP, jeśli nie masz istniejącego pliku MANIFEST.in i tylko jeśli używasz wersji 2.7+.
Johnus
29
Poważnie, czuję, że ten bilet jest sesją terapii grupowej dla ludzi używających setuptools i odkrywających, jak okropne miejsce znaleźli się w życiu.
Matt Joyce,
32

Właśnie miałem ten sam problem. Rozwiązaniem było po prostu usunięcie include_package_data=True.

Po przeczytaniu tutaj zdałem sobie sprawę, że include_package_datama to na celu uwzględnienie plików z kontroli wersji , a nie tylko „dołączanie danych pakietu”, jak sugeruje nazwa. Z dokumentów:

Pliki danych [z include_package_data] muszą znajdować się pod kontrolą CVS lub Subversion

...

Jeśli chcesz mieć dokładniejszą kontrolę nad tym, jakie pliki są dołączane (na przykład, jeśli masz pliki dokumentacji w katalogach pakietów i chcesz je wykluczyć z instalacji), możesz również użyć package_datasłowa kluczowego.

Usunięcie tego argumentu naprawiło to, co jest przypadkowym powodem, dla którego działał również po przejściu na distutils, ponieważ nie przyjmuje tego argumentu.

Joe
źródło
2
Moje doświadczenie jest inne, miałem ten sam problem bez include_package_data=Truewpisu. Jedynym rozwiązaniem dla mnie jest dodanie wpisu w Manifeście, jak zasugerowano powyżej. Pamiętaj, że używałem setuptools, może twoja wersja działa z 'dystrybucją'?
TimStaley
4
Rzeczywisty powód, dla którego usunięcie include_package_datarozwiązuje problem znajduje się dalej w oryginalnym tekście - w przypadku użycia include_package_dataargumentu specyficznego dla setuptools pliki określone przez package_datanie zostaną automatycznie dodane do manifestu, chyba że zostaną wymienione w MANIFEST.inpliku.
Piotr Dobrogost
Jaki jest przypadek użycia package_dataustawienia niepustej listy i określenia include_package_data=False? Dlaczego miałbyś dwukrotnie określać pliki w MANIFEST.ini package_data?
Herbert
21

Postępowanie zgodnie z zaleceniem @Joe, aby usunąć include_package_data=Truelinię, również działało dla mnie.

Aby rozwinąć trochę więcej, mam żadnego MANIFEST.in pliku. Używam Gita, a nie CVS.

Repozytorium ma taki kształt:

/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...
        ], },
)

Używam python setup.py sdistdystrybucji źródłowej (nie próbowałem binarnego).

A kiedy jestem w zupełnie nowym środowisku wirtualnym, mam myproject-4.19.tar.gzplik, i używam

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

Poza tym, że wszystko jest instalowane w moim środowisku wirtualnym site-packages, te specjalne pliki danych są instalowane w /opt/local/myproject/datai /opt/local/myproject/etc.

HeyWatchThis
źródło
16

include_package_data=True pracował dla mnie.

Jeśli używasz git, pamiętaj, aby uwzględnić setuptools-gitw install_requires. O wiele mniej nudne niż posiadanie Manifestlub włączenie wszystkich ścieżek package_data(w moim przypadku jest to aplikacja django z wszelkiego rodzaju statystyką)

( wkleiłem komentarz, który napisałem, ponieważ k3-rnc wspomniał, że jest faktycznie pomocny)

Vincent
źródło
7

Aktualizacja : ta odpowiedź jest stara, a informacje nie są już aktualne. Wszystkie konfiguracje setup.py powinny używać import setuptools. Dodałem pełniejszą odpowiedź na https://stackoverflow.com/a/49501350/64313


Rozwiązałem to, przechodząc na distutils. Wygląda na to, że funkcja dystrybucji jest przestarzała i / lub uszkodzona.

from distutils.core import setup

setup(
   name='myapp',
   packages=['myapp'],
   package_data={
      'myapp': ['data/*.txt'],
   },
)
cmcginty
źródło
2
dystrybucja nie jest przestarzała, zastępuje distutils. Nie wiem, dlaczego miałeś problem, ale to nie jest powód.
agf
1
To była odpowiedź, którą otrzymałem od IRC, więc komu wierzę? Jeśli masz przykład pracy z dystrybucją, byłbym wdzięczny.
cmcginty
6
wyjaśnienie: dystrybucja ma zastąpić setuptools, oba są zbudowane na bazie distutils. Sam distutils zostanie ostatecznie zastąpiony nowym pakietem, zwanym „distutils2” w pythonie2 i „opakowaniami” w pythonie3
Kevin Horn
1
Przejście na distutils rozwiązało mój problem, include_package_data=Truektóry nie był honorowany. Dzięki temu ustawieniu potrzebujesz tylko pliku MANIFEST.in - nie ma potrzeby duplikowania listy plików w package_dataustawieniu.
Daniel Sokolowski
4

Starożytne pytanie, a jednak ... zarządzanie pakietami w Pythonie naprawdę pozostawia wiele do życzenia. Tak więc miałem przypadek użycia instalacji przy użyciu pip lokalnie do określonego katalogu i byłem zaskoczony, że ścieżki danych pakietu i plików danych nie wyszły. Nie chciałem dodawać kolejnego pliku do repozytorium, więc ostatecznie wykorzystałem opcję data_files i setup.py --install-data; coś takiego

pip install . --install-option="--install-data=$PWD/package" -t package  
Mat Baker
źródło
3

Miałem ten sam problem przez kilka dni, ale nawet ten wątek nie był w stanie mi pomóc, ponieważ wszystko było zagmatwane. Zrobiłem więc swoje badania i znalazłem następujące rozwiązanie:

Zasadniczo w tym przypadku powinieneś zrobić:

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'],
   },
)

Pełne inne odpowiedzi na temat przepełnienia stosu tutaj

moctarjallo
źródło
Próbowałem, ale nadal nic nie zostało skopiowane.
gerrit
3

Po prostu usuń linię:

include_package_data=True,

ze skryptu instalacyjnego i będzie działać dobrze. (Przetestowane przed chwilą z najnowszymi narzędziami konfiguracyjnymi).

Ian
źródło
To szalone, ale działa zarówno z, jak sdisti bdist_wheel, czy sprawdziłeś dlaczego?
Szabolcs
1
Mogę rzeczywiście potwierdzić, że sdistignoruje package_datato ustawienie.
Sander Steffann
W tym momencie minęły miesiące, ale wydaje mi się, że kopałem w kodzie, dwukrotnie się zgubiłem, zabrałem BARDZO drobnozębny grzebień do dokumentacji i zyskałem satysfakcję. Najwyraźniej różne przykładowe skrypty zawierają tę flagę i powoduje to niekończące się bóle głowy.
Ian
1

Korzystanie z setup.cfg (setuptools ≥ 30.3.0)

Począwszy od setuptools 30.3.0 (wydany 2016-12-08), możesz zachować swój setup.pybardzo mały rozmiar i przenieść konfigurację do setup.cfgpliku. Dzięki temu podejściu możesz umieścić dane pakietu w [options.package_data]sekcji:

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

W takim przypadku Twój setup.pymoże być tak krótki, jak:

from setuptools import setup
setup()

Aby uzyskać więcej informacji, zobacz konfigurowanie instalacji przy użyciu plików setup.cfg .

Jest jakaś rozmowa o deprecjacjęsetup.cfg na korzyść pyproject.toml, jak zaproponowano w PEP 518 , ale to wciąż tymczasowy stan na 2020-02-21.

gerrit
źródło
Ta odpowiedź nie wspomina o pliku MANIFEST, więc myślę, że tak naprawdę nie będzie działać z sdists. Tylko z kołami. Powinieneś o tym wspomnieć.
wim
@wim Nie mam wystarczającej wiedzy na temat MANIFESTU, sdist i kół, aby odpowiedzieć na to pytanie. To zadziałało dla mnie przy użyciu pip install.
gerrit
Dzieje się tak pip install, ponieważ w przypadku wystarczająco nowoczesnych wersji pip najpierw zbuduje koło, a następnie je zainstaluje. Nadal dla wielu użytkowników to podejście po cichu nie będzie obejmować danych pakietu. Zobacz zaakceptowaną odpowiedź i komentarze pod nią, aby uzyskać szczegółowe informacje. Użycie a setup.cfgjest tak naprawdę innym sposobem zapisania tego, co OP już robił w setup.pypytaniu (przekazując package_dataargument słowa kluczowego w wywołaniu do setup), więc nie sądzę, aby było to szczególnie pomocne jako odpowiedź na to pytanie . W ogóle nie rozwiązuje podstawowego problemu.
wim