Ich schreibe ein Python-Paket mit Modulen, die Datendateien in einem ./data/
Unterverzeichnis öffnen müssen . Im Moment habe ich die Pfade zu den Dateien fest in meine Klassen und Funktionen codiert. Ich möchte robusteren Code schreiben, der auf das Unterverzeichnis zugreifen kann, unabhängig davon, wo es auf dem System des Benutzers installiert ist.
Ich habe verschiedene Methoden ausprobiert, aber bisher hatte ich kein Glück. Es scheint, dass die meisten Befehle "aktuelles Verzeichnis" das Verzeichnis des Python-Interpreters des Systems und nicht das Verzeichnis des Moduls zurückgeben.
Dies scheint ein triviales, häufiges Problem zu sein. Trotzdem kann ich es nicht herausfinden. Ein Teil des Problems besteht darin, dass meine Datendateien keine .py
Dateien sind, sodass ich keine Importfunktionen und dergleichen verwenden kann.
Irgendwelche Vorschläge?
Im Moment sieht mein Paketverzeichnis so aus:
/
__init__.py
module1.py
module2.py
data/
data.txt
Ich versuche , den Zugang data.txt
von module*.py
!
Antworten:
Sie können
__file__
den Pfad zum Paket folgendermaßen abrufen:quelle
__file__
nicht mit py2exe, da der Wert der Pfad zur Zip-Datei ist.Die Standardmethode hierfür sind setuptools-Pakete und pkg_resources.
Sie können Ihr Paket gemäß der folgenden Hierarchie anordnen und die Paket-Setup-Datei so konfigurieren, dass sie über diesen Link auf Ihre Datenressourcen verweist:
http://docs.python.org/distutils/setupscript.html#installing-package-data
Sie können diese Dateien dann mithilfe von pkg_resources gemäß diesem Link erneut finden und verwenden:
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access
quelle
python-setuptools
nur darauf verlassen? Bisher__file__
funktioniert gut für mich.from pkg_resources import resource_filename open(resource_filename('data', 'data.txt'), 'rb')
importlib.resources
ersetztpkg_resources
für diesen Zweck (wegen der Performance - Probleme).Um eine Lösung zu bieten, die heute funktioniert. Verwenden Sie diese API auf jeden Fall, um nicht alle diese Räder neu zu erfinden.
Ein echter Dateisystem-Dateiname wird benötigt. Gezippte Eier werden in ein Cache-Verzeichnis extrahiert:
Gibt ein lesbares dateiähnliches Objekt für die angegebene Ressource zurück. Es kann sich um eine tatsächliche Datei, ein StringIO oder ein ähnliches Objekt handeln. Der Stream befindet sich im "Binärmodus" in dem Sinne, dass alle Bytes in der Ressource unverändert gelesen werden.
Paketerkennung und Ressourcenzugriff mit pkg_resources
quelle
Es macht oft keinen Sinn, eine Antwort zu geben, die Details des Codes enthält, der nicht so funktioniert, wie er ist, aber ich glaube, dass dies eine Ausnahme ist. Python 3.7 hinzugefügt
importlib.resources
, das ersetzen sollpkg_resources
. Es würde für den Zugriff auf Dateien in Paketen funktionieren, deren Namen keine Schrägstriche enthalten , d. H.dh Sie könnten zum Beispiel mit
data2.txt
innerhalb des Pakets zugreifenfoo
aber es würde mit einer Ausnahme für scheitern
Dies kann nicht festgelegt werden , außer indem man
__init__.py
indata
und dann als Paket mit:Der Grund für dieses Verhalten ist "es ist beabsichtigt" ; aber das Design könnte sich ändern ...
quelle
"This was a deliberate choice, but I think you have a valid use case. @brettcannon what do you think? And if we allow this, should we make sure it gets into Python 3.7?"
Sie benötigen einen Namen für Ihr gesamtes Modul. Sie erhalten einen Verzeichnisbaum, in dem dieses Detail nicht aufgeführt ist. Bei mir hat dies funktioniert:
Insbesondere setuptools scheint keine Dateien aufzulösen, die auf einer Namensübereinstimmung mit gepackten Datendateien basieren. Sie müssen also das
data/
Präfix so ziemlich einfügen, egal was passiert . Sie können verwenden,os.path.join('data', 'data.txt)
wenn Sie alternative Verzeichnis-Trennzeichen benötigen. Im Allgemeinen finde ich jedoch keine Kompatibilitätsprobleme mit fest codierten Verzeichnis-Trennzeichen im Unix-Stil.quelle
Ich glaube, ich habe eine Antwort gefunden.
Ich erstelle ein Modul data_path.py, das ich in meine anderen Module importiere, die Folgendes enthalten:
Und dann öffne ich alle meine Dateien mit
quelle
pkg_resources.resource_string('pkg_name', 'data/file.txt')
__file__
irgendwo verwendet haben. In meinem Fall verwende ich eine Bibliothek, die wirklich Pfade und keine Streams will. Natürlich könnte ich die Dateien vorübergehend auf die Festplatte schreiben, aber da ich faul bin, verwende ich nur die Funktion von setuptools.