Setuptools: Paketdatenordner

Ich verwende setuptools, um mein Pythonpaket zu verteilen. Jetzt muss ich zusätzliche Datendateien verteilen.

Von dem, was ich von der setuptools Dokumentation gesammelt habe, muss ich meine Datendateien im Paketverzeichnis haben. Allerdings würde ich lieber meine Datendateien in einem Unterverzeichnis im Wurzelverzeichnis haben.

Was ich gerne vermeiden möchte:

/ #root |- src/ | |- mypackage/ | | |- data/ | | | |- resource1 | | | |- [...] | | |- __init__.py | | |- [...] |- setup.py 

Was möchte ich stattdessen haben:

 / #root |- data/ | |- resource1 | |- [...] |- src/ | |- mypackage/ | | |- __init__.py | | |- [...] |- setup.py 

Ich fühle mich einfach nicht wohl mit so vielen Unterverzeichnissen, wenn es nicht wesentlich ist. Ich finde keinen Grund, warum ich die Dateien in das Paketverzeichnis stellen muss. Es ist auch umständlich, mit so vielen verschachtelten Unterverzeichnissen IMHO zu arbeiten. Oder gibt es einen guten Grund, der diese Einschränkung rechtfertigen würde?

4 Solutions collect form web for “Setuptools: Paketdatenordner”

Option 1: Als Paketdaten installieren

Der Hauptvorteil der Platzierung von Datendateien in der Wurzel Ihres Python-Pakets ist, dass es Ihnen ermöglicht, sich Sorgen zu machen, wo die Dateien auf dem System eines Benutzers leben, was Windows, Mac, Linux, eine mobile Plattform oder ein Ei sein kann. Sie können immer die Verzeichnisdaten relativ zu Ihrem Python-Paket-Root finden, egal wo oder wie es installiert ist.

Zum Beispiel, wenn ich ein Projekt-Layout wie so haben:

 project/ foo/ __init__.py data/ resource1/ foo.txt 

Sie können eine Funktion zu __init__.py , um einen absoluten Pfad zu einer __init__.py zu finden:

 import os _ROOT = os.path.abspath(os.path.dirname(__file__)) def get_data(path): return os.path.join(_ROOT, 'data', path) print get_data('resource1/foo.txt') 

Ausgänge:

 /Users/pat/project/foo/data/resource1/foo.txt 

Nachdem das Projekt als Ei installiert ist, ändert sich der Pfad zu den data , aber der Code muss sich nicht ändern:

 /Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt 

Option 2: an festen Standort installieren

Die Alternative wäre, Ihre Daten außerhalb des Python-Pakets zu platzieren und dann entweder:

  1. Lassen Sie den Standort der data über eine Konfigurationsdatei, Befehlszeilenargumente oder
  2. Setzen Sie den Standort in Ihren Python-Code ein.

Dies ist weit weniger wünschenswert, wenn Sie planen, Ihr Projekt zu verteilen. Wenn Sie dies wirklich tun möchten, können Sie Ihre data überall auf dem Zielsystem installieren, indem Sie das Ziel für jede Gruppe von Dateien angeben, indem Sie eine Liste von Tupeln übergeben:

 from setuptools import setup setup( ... data_files=[ ('/var/data1', ['data/foo.txt']), ('/var/data2', ['data/bar.txt']) ] ) 

Aktualisiert : Beispiel einer Shell-Funktion zum rekursiven Greifen von Python-Dateien:

 atlas% function grep_py { find . -name '*.py' -exec grep -Hn $* {} \; } atlas% grep_py ": \[" ./setup.py:9: package_data={'foo': ['data/resource1/foo.txt']} 

Ich denke, ich fand einen guten Kompromiss, der Ihnen erlaubt, die folgende Struktur zu übernehmen:

 / #root |- data/ | |- resource1 | |- [...] |- src/ | |- mypackage/ | | |- __init__.py | | |- [...] |- setup.py 

Sie sollten Daten als package_data installieren, um die in der Beispielbias-Antwort beschriebenen Probleme zu vermeiden, aber um die Dateistruktur, die Sie Ihrem setup.py hinzufügen möchten, zu mantain:

 try: os.symlink('../../data', 'src/mypackage/data' setup( ... package_data = {'mypackage': ['data/*']} ... ) finally: os.unlink('src/mypackage/data') 

Auf diese Weise schaffen wir die passende Struktur "just in time" und mantain unsere Quelle Baum organisiert.

Um auf solche Datendateien innerhalb Ihres Codes zuzugreifen, verwenden Sie einfach:

data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')

Ich habe immer noch nicht gern, "mypackage" im Code anzugeben, da die Daten mit diesem Modul nichts zu tun haben könnten, aber ich denke, es ist ein guter Kompromiss.

Ich verwende setuptools, um native OS-Pakete wie RPMs und DEBs zu erstellen. Das Projekt-Layout, das ich verwende, ist.

 <project>/ lib/ -> .../lib/pythonX/site-packages/ bin/ -> .../bin/ etc/ -> /etc/ doc/ man/ -> .../man/man1/ share/ -> .../share/doc/<project>/ 

Meine Datei setup.py führt die entsprechende Mapping wie oben beschrieben aus. Ich finde dieses Layout ideal für Python. Die produzierten Pakete sind verlagerbar, aber standardmäßig unter /usr/local/ .

Ich denke, dass man grundsätzlich alles als Argument * data_files * zum Setup () geben kann .

  • Programmatische Erkennung von System-Proxy-Einstellungen unter Windows XP mit Python
  • Paket nur Binär kompiliert. So Dateien einer Python-Bibliothek mit Cython kompiliert
  • Verwenden von easy_install in einem Python-Skript?
  • Cx_Freeze kann nicht finden pkg_resources /*.* '
  • Ermittlung der Version von easy_install / setuptools
  • Was ist der richtige Weg, um Paketversion mit setup.py und dem Paket zu teilen?
  • Richtigen Weg, um Skripts Verzeichnis von setup.py in Python distutils zu finden?
  • Python: Pip kann nicht setup.py finden
  • Wie verwende ich Daten in package_data aus Quellcode?
  • Erste Schritte, um das PyPI-Repository zu ignorieren
  • Setuptools: SVN-Revision aus einem übergeordneten Verzeichnis finden
  • Python ist die beste Programmiersprache der Welt.