it-swarm.com.de

Wie beziehe ich mich auf relative Pfade von Ressourcen, wenn ich mit einem Code-Repository in Python arbeite?

Wir arbeiten mit einem Code-Repository, das sowohl für Windows als auch für Linux bereitgestellt wird - manchmal in verschiedenen Verzeichnissen. Wie sollte eines der Module im Projekt auf eine der Nicht-Python-Ressourcen im Projekt verweisen (CSV-Dateien usw.)?

Wenn wir etwas machen wie:

thefile=open('test.csv')

oder:

thefile=open('../somedirectory/test.csv')

Dies funktioniert nur, wenn das Skript in einem bestimmten Verzeichnis oder einer Teilmenge der Verzeichnisse ausgeführt wird.

Was ich gerne machen würde, ist so etwas wie:

path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)

Ist das der richtige Weg? Ist es möglich?

171
olamundo

Versuchen Sie, einen Dateinamen relativ zum aktuellen Dateipfad zu verwenden. Beispiel für './my_file':

fn = os.path.join(os.path.dirname(__file__), 'my_file')

In Python 3.4+ können Sie auch pathlib verwenden:

fn = pathlib.Path(__file__).parent / 'my_file'
229
c089

Wenn Sie Setup-Tools verwenden oder (eine setup.py-Installation) verteilen, scheint die "richtige" Methode für den Zugriff auf diese gepackten Ressourcen package_resources zu verwenden.

In Ihrem Fall wäre das Beispiel

import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")

Was natürlich die Ressource und die gelesenen Binärdaten liest, wäre der Wert von my_data

Wenn Sie nur den Dateinamen benötigen, können Sie auch verwenden

resource_filename(package_or_requirement, resource_name)

Beispiel:

resource_filename("MyPackage","foo.dat")

Der Vorteil ist, dass es garantiert funktioniert, auch wenn es sich um eine Archivdistribution wie ein Ei handelt.

Siehe http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api

37
Sharoon Thomas

In Python beziehen sich Pfade auf das aktuelle Arbeitsverzeichnis , aus dem in den meisten Fällen das Verzeichnis stammt mit dem du dein programm ausführst. Das aktuelle Arbeitsverzeichnis ist höchstwahrscheinlich nicht dasselbe wie das Verzeichnis Ihrer Moduldatei, daher ist die Verwendung eines Pfads relativ zu Ihrer aktuellen Moduldatei immer schlecht Wahl.

Die Verwendung des absoluten Pfads sollte die beste Lösung sein:

import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
14
skyfree

Ich benutze oft etwas Ähnliches:

import os
DATA_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'datadir'))

# if you have more paths to set, you might want to shorten this as
here = lambda x: os.path.abspath(os.path.join(os.path.dirname(__file__), x))
DATA_DIR = here('datadir') 

pathjoin = os.path.join
# ...
# later in script
for fn in os.listdir(DATA_DIR):
    f = open(pathjoin(DATA_DIR, fn))
    # ...

Die Variable

__file__

enthält den Dateinamen des Skripts, in das Sie diesen Code geschrieben haben, sodass Sie Pfade relativ zum Skript erstellen können, die jedoch immer noch mit absoluten Pfaden geschrieben sind. Es funktioniert aus mehreren Gründen ganz gut:

  • pfad ist absolut, aber immer noch relativ
  • das Projekt kann weiterhin in einem relativen Container bereitgestellt werden

Sie müssen jedoch auf Plattformkompatibilität achten - Windows 'os.pathsep unterscheidet sich von UNIX.

12
user137673
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)

Sie versuchen auch, Ihr cwd mit os.path.abspath(os.getcwd()) zu normalisieren. Weitere Infos hier .

5
gavoja

Sie können die eingebaute Variable __file__ Verwenden. Es enthält den Pfad der aktuellen Datei. Ich würde getBaseOfProject in einem Modul im Stammverzeichnis Ihres Projekts implementieren. Dort würde ich den Pfad-Teil von __file__ Bekommen und das zurückgeben. Diese Methode kann dann überall in Ihrem Projekt verwendet werden.

2
Achim

Ich war hier ein bisschen ratlos. Wollte einige Ressourcendateien in eine Raddatei packen und darauf zugreifen. Hat das Paket die Manifest-Datei verwendet, aber pip install hat es nicht installiert, es sei denn, es war ein Unterverzeichnis. Hoffen, dass diese Szenen helfen

├── cnn_client
│   ├── image_preprocessor.py
│   ├── __init__.py
│   ├── resources
│   │   ├── mscoco_complete_label_map.pbtxt
│   │   ├── retinanet_complete_label_map.pbtxt
│   │   └── retinanet_label_map.py
│   ├── tf_client.py

MANIFEST.in

recursive-include cnn_client/resources *

Erstellt ein weel mit standard setup.py. pip hat die Raddatei installiert. Überprüfen Sie nach der Installation, ob Ressourcen installiert sind. Sie sind

ls /usr/local/lib/python2.7/dist-packages/cnn_client/resources

mscoco_complete_label_map.pbtxt
retinanet_complete_label_map.pbtxt 
 retinanet_label_map.py  

In tfclient.py, um auf diese Dateien zuzugreifen. von

templates_dir = os.path.join(os.path.dirname(__file__), 'resources')
 file_path = os.path.join(templates_dir, \
            'mscoco_complete_label_map.pbtxt')
        s = open(file_path, 'r').read()

Und es funktioniert.

0
Alex Punnen