MANIFEST.in bei "python setup.py install" ignoriert - keine Datendateien installiert?

87

Hier ist mein abgespecktes setup.py-Skript, bei dem Nicht-Code-Inhalte entfernt wurden:

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

Wenn ich "python setup.py install sdist" ausführe, erhalte ich eine schöne .tar.gz mit einem Stammordner "whyteboard-0.41", in dem sich meine Ordner locale / images / und whyteboard-help / befinden. Dies hat auch mein whyteboard.py-Skript, das mein Programm aus dem whyteboard-Quellpaket heraus startet.

So:

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

Dies spiegelt die Quelle meines Programms wider, ist, wie alles sein sollte und ist korrekt.

Wenn ich jedoch "python setup.py install" ausführe, wird keine meiner Datendateien geschrieben - nur das Quellpaket "whyteboard" und die Datei whyteboard.py werden in /usr/local/lib/python2.6/dist-packages/ abgelegt. .

Im Idealfall möchte ich, dass dieselbe Verzeichnisstruktur wie die in der Datei .tar.gz generierte in dist-Paketen erstellt wird, da mein Programm auf diese Weise erwartet, nach seinen Ressourcen zu suchen.

Wie kann ich "installieren", um diese Verzeichnisstruktur zu erstellen? Soweit ich das beurteilen kann, scheint es meine Manifestdatei zu ignorieren.

Steven Sproat
quelle

Antworten:

30

Einige Anmerkungen zusätzlich zu Neds Antwort (die das Kernproblem betrifft):

Distutils installiert keine Python-Pakete und -Module in einem projektbezogenen Unterverzeichnis innerhalb site-packages(oder dist-packagesunter Debian / Ubuntu): Sie werden site-packages, wie Sie gesehen haben, direkt in installiert . Das enthaltende whyteboard-xxVerzeichnis in Ihrer SD-Liste ist also in der endgültig installierten Form nicht vorhanden.

Dies impliziert unter anderem, dass Sie darauf achten sollten, Ihre Namen so zu benennen data_files, dass klargestellt wird, zu welchem ​​Projekt sie gehören, da diese Dateien / Verzeichnisse direkt im globalen site-packagesVerzeichnis installiert werden und nicht in einem enthaltenen whyteboardVerzeichnis.

Oder Sie könnten stattdessen Ihre Daten package_datades whyteboardPakets erstellen (was bedeutet, dass es in diesem Paket leben muss, dh neben __init__.py), und dann ist dies kein Problem.

Schließlich macht es wenig Sinn, sowohl ein whyteboard.pyModul py_modulesals auch ein whyteboard/__init__.pyPaket zu haben packages. Die beiden schließen sich gegenseitig aus, und wenn Sie beide haben, wird das whyteboard.pyModul beim Import zugunsten des gleichnamigen Pakets ignoriert.

Wenn whyteboard.pyes sich nur um ein Skript handelt und nicht importiert werden soll, sollten Sie die Skriptoption dafür verwenden und es entfernen py_modules.

Carl Meyer
quelle
1
Das ist bedauerlich. Ich mag die Idee, Paketdaten zu haben, nicht - für mich ist es sinnvoller, dass diese Ressourcen außerhalb des Quellverzeichnisses leben. Ich mag es auch nicht, wenn dem Programmnamen Verzeichnisnamen vorangestellt werden müssen (obwohl ich das bereits für die Hilfedateien mache). Hmm ..
Steven Sproat
67

MANIFEST.inteilt Distutils mit, welche Dateien in die Quelldistribution aufgenommen werden sollen, hat jedoch keinen direkten Einfluss darauf, welche Dateien installiert werden. Dazu müssen Sie die entsprechenden Dateien in die setup.pyDatei aufnehmen, in der Regel entweder als Paketdaten oder als zusätzliche Dateien .

Ned Deily
quelle
Ich habe versucht, eine Liste mit Paketdaten hinzuzufügen, aber keine der von mir angegebenen Dateien wurde verwendet. Ich war mir nicht sicher, ob die Speicherorte der Dateien im Verhältnis zur Gesamtinstallation des Pakets installiert wurden. Trotzdem schrieb es meine Dateien immer noch nicht in der richtigen Verzeichnisstruktur, die ich erwartet hatte.
Steven Sproat
Die in dieser Antwort verknüpfte Dokumentation enthält alle Informationen, die Sie zum Installieren von Datendateien und Paketdaten benötigen. Wenn diese Optionen für Sie nicht funktionieren, aktualisieren Sie Ihre Frage bitte mit der genauen Syntax, den Ergebnissen und den Erwartungen.
Carl Meyer
4
Das funktioniert bei mir: Wenn Sie meine MANIFEST.in-Einträge in den data_packages von setup.py duplizieren, funktioniert alles. Danke Ned - ich habe diesen Punkt jahrelang nicht verstanden. Hoffentlich machen meine Distutils / Setuptools / Distribute-Erfahrungen jetzt mehr Sinn.
Jonathan Hartley
7
Ist dieses Konzept, Dateien in das Paket aufnehmen zu können, die nicht installiert werden, sinnvoll? Wann würde es verwendet werden?
Roger Dahl
27

Ich konnte nicht herausfinden, warum meine MANIFEST.inDatei beim Ausführen ignoriert wurde python setup.py install- es stellt sich heraus, dass include_package_data=Truedas Problem gelöst ist. Die package_dataOption ist eigentlich nicht erforderlich.

Greg
quelle
guter Fang, warum include_package_data=Trueist nicht Standardwert?
Liang
8

Unter Python 2.6.1 unter Mac OS X hatte ich absolut kein Glück, außer mit dem Parameter data_files in setup.py. Alles mit MANIFEST.in führte einfach dazu, dass Dateien im dist-Paket enthalten waren, aber nie installiert wurden. Ich habe einige andere Pakete überprüft und sie haben tatsächlich data_files verwendet, um zusätzliche Dateien anzugeben.

Ich habe eine kurze Funktion erstellt, mit deren Hilfe alle Dateien aus einem Verzeichnisbaum in der Liste aufgelistet werden können

(target_dir, [file list]) Format, das data_files erwartet:

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

Jetzt kann ich dies einfach in meinem Setup-Aufruf aufrufen:

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

Und alles in diesen Bäumen wird installiert.

Scott Persinger
quelle
11
Das ist großartig, aber wo wird es installiert? Wenn ich "pip install" verwende, werden meine Datendateien im Stammverzeichnis meiner virtuellen Umgebung gespeichert (dh in einem einzelnen Verzeichnis, das von allen Paketen der virtuellen Umgebung gemeinsam genutzt wird). Wenn Sie "setup.py install" verwenden, werden meine Datendateien in "site-" gespeichert. packages / <mypackage> .egg / ". Wenn es sich bei den Dateien um Daten handelt, die zur Laufzeit benötigt werden, ist es für meinen Code in keinem Fall trivial, diese Dateien zu finden, und natürlich muss ich zur Laufzeit beide Verzeichnisse durchsuchen. Wenn die Dateien meine LIZENZ-Datei sind, ist es für meine Benutzer in keinem Fall trivial, von meiner Quelle zur LIZENZ zu gelangen. Verwirrt.
Jonathan Hartley
8

Sie sollten Setuptools verwenden:

#!/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'],
)

Dies verwendet nicht die MANIFEST-Datei, um den Job auszuführen, sondern enthält alle erforderlichen Dateien.

Juho Rutila
quelle
Das hat bei mir mit Setuptools funktioniert . Ich erstelle ein Debian-Paket und sehe, dass meine im package_dataWörterbuch aufgelisteten Glade-Dateien erst nach dem Hinzufügen an der richtigen Stelle angezeigt werden include_package_data=Tru.
mlt
3

Minimales veröffentlichtes ausführbares Beispiel

Schlüssel zum Mitnehmen: hat nur MANIFEST.infür mich funktioniert,package_data nicht.

Getestet unter Ubuntu 19.10, Python 3.7.5, Wheel == 0.32.3, Setuptools == 41.1.0, Twine == 3.1.1.

Wie Endbenutzer das Paket unter https://pypi.org/project/python-sample-package-with-data/ verwenden :

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

Erwartete Ausgabe:

hello data

Wie Betreuer es veröffentlichen:

# 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

Die eigentlichen Dateien:

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-Beispiel-Paket-mit-Daten

#!/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'],
)

Literaturverzeichnis:

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