Nous travaillons avec un référentiel de code déployé à la fois sous Windows et Linux - parfois sur des répertoires différents. Comment l'un des modules du projet doit-il se référer à l'une des ressources non Python du projet (fichiers CSV, etc.)?
Si nous faisons quelque chose comme:
thefile=open('test.csv')
ou:
thefile=open('../somedirectory/test.csv')
Cela fonctionnera uniquement lorsque le script sera exécuté à partir d'un répertoire spécifique ou d'un sous-ensemble des répertoires.
Ce que j'aimerais faire est quelque chose comme:
path=getBasePathOfProject()+'/somedirectory/test.csv'
thefile=open(path)
Est-ce la bonne façon? C'est possible?
Essayez d’utiliser un nom de fichier relatif au chemin des fichiers actuels. Exemple pour './my_file':
fn = os.path.join(os.path.dirname(__file__), 'my_file')
Dans Python 3.4+, vous pouvez également utiliser pathlib :
fn = pathlib.Path(__file__).parent / 'my_file'
Si vous utilisez des outils d'installation ou si vous distribuez (une installation setup.py), la "bonne" façon d'accéder à ces ressources empaquetées semble utiliser package_resources.
Dans votre cas, l'exemple serait
import pkg_resources
my_data = pkg_resources.resource_string(__name__, "foo.dat")
Ce qui bien sûr lit la ressource et les données binaires lues seraient la valeur de my_data
Si vous avez juste besoin du nom de fichier, vous pouvez aussi utiliser
resource_filename(package_or_requirement, resource_name)
Exemple:
resource_filename("MyPackage","foo.dat")
L'avantage est que son fonctionnement est garanti même s'il s'agit d'une distribution d'archives comme un Egg.
Voir http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api
En Python, les chemins sont relatifs au répertoire de travail actuel , qui est dans la plupart des cas le répertoire à partir duquel vous exécutez votre programme. . Le répertoire de travail actuel est très probablement différent du répertoire de votre fichier de module. Il est donc toujours mauvais d'utiliser un chemin relatif à votre fichier de module actuel. choix.
Utiliser le chemin absolu devrait être la meilleure solution:
import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
J'utilise souvent quelque chose de similaire à ceci:
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))
# ...
La variable
__file__
contient le nom de fichier du script dans lequel vous écrivez ce code, vous pouvez donc créer des chemins relatifs au script, mais toujours écrits avec des chemins absolus. Cela fonctionne assez bien pour plusieurs raisons:
Mais vous devez surveiller la compatibilité de la plate-forme - os.pathsep de Windows est différent d’UNIX.
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)
Vous essayez également de normaliser votre cwd
en utilisant os.path.abspath(os.getcwd())
. Plus d'infos ici .
Vous pouvez utiliser la variable de construction __file__
. Il contient le chemin du fichier actuel. J'implémenterais getBaseOfProject dans un module à la racine de votre projet. Là, j'obtiendrais la partie chemin de __file__
et je le renverrais. Cette méthode peut ensuite être utilisée partout dans votre projet.
Je suis un peu coincé ici. Voulait empaqueter des fichiers de ressources dans un fichier wheel et y accéder. L'emballage a-t-il utilisé le fichier manifeste, mais pip install ne l'installait pas sauf s'il s'agissait d'un sous-répertoire. En espérant que ces plans vous aideront
├── 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 *
Créé un weel en utilisant setup.py standard. pip a installé le fichier de roue. Après l'installation, vérifiez si les ressources sont installées. Elles sont
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
Dans tfclient.py pour accéder à ces fichiers. de
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()
Et il fonctionne.