J'écris un package python avec des modules qui doivent ouvrir des fichiers de données dans un ./data/
sous-répertoire. En ce moment, j'ai les chemins d'accès aux fichiers codés en dur dans mes classes et fonctions. Je voudrais écrire un code plus robuste qui peut accéder au sous-répertoire indépendamment de l'endroit où il est installé sur le système de l'utilisateur.
J'ai essayé différentes méthodes, mais jusqu'à présent, je n'ai pas eu de chance. Il semble que la plupart des commandes du "répertoire courant" retournent le répertoire de l'interpréteur python du système, et non le répertoire du module.
Cela semble être un problème banal et courant. Pourtant, je n'arrive pas à comprendre. Une partie du problème est que mes fichiers de données ne sont pas .py
fichiers, donc je ne peux pas utiliser les fonctions d'importation et autres.
Aucune suggestion?
En ce moment, mon répertoire de packages ressemble à:
/
__init__.py
module1.py
module2.py
data/
data.txt
J'essaie d'accéder à data.txt
de module*.py
Merci!
Vous pouvez utiliser __file__
pour obtenir le chemin d'accès au package, comme ceci:
import os
this_dir, this_filename = os.path.split(__file__)
DATA_PATH = os.path.join(this_dir, "data", "data.txt")
print open(DATA_PATH).read()
La façon standard de le faire est d'utiliser les packages setuptools et pkg_resources.
Vous pouvez disposer votre package selon la hiérarchie suivante et configurer le fichier de configuration du package pour pointer vers vos ressources de données, selon ce lien:
http://docs.python.org/distutils/setupscript.html#installing-package-data
Vous pouvez ensuite retrouver et utiliser ces fichiers à l'aide de pkg_resources, selon ce lien:
http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access
import pkg_resources
DATA_PATH = pkg_resources.resource_filename('<package name>', 'data/')
DB_FILE = pkg_resources.resource_filename('<package name>', 'data/sqlite.db')
Pour fournir une solution qui fonctionne aujourd'hui. Utilisez certainement cette API pour ne pas réinventer toutes ces roues.
Un vrai nom de fichier du système de fichiers est nécessaire. Les œufs zippés seront extraits dans un répertoire cache:
from pkg_resources import resource_filename, Requirement
path_to_vik_logo = resource_filename(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")
Renvoie un objet de type fichier lisible pour la ressource spécifiée; il peut s'agir d'un fichier réel, d'un StringIO ou d'un objet similaire. Le flux est en "mode binaire", en ce sens que tous les octets de la ressource seront lus tels quels.
from pkg_resources import resource_stream, Requirement
vik_logo_as_stream = resource_stream(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")
Découverte de packages et accès aux ressources à l'aide de pkg_resources
Je pense que j'ai traqué une réponse.
Je crée un module data_path.py, que j'importe dans mes autres modules contenant:
data_path = os.path.join(os.path.dirname(__file__),'data')
Et puis j'ouvre tous mes fichiers avec
open(os.path.join(data_path,'filename'), <param>)
Vous avez besoin d'un nom pour l'ensemble de votre module, on vous donne une arborescence de répertoires qui ne répertorie pas ce détail, pour moi, cela a fonctionné:
import pkg_resources
print(
pkg_resources.resource_filename(__name__, 'data/data.txt')
)
Setuptools ne semble pas résoudre les fichiers basés sur une correspondance de nom avec des fichiers de données compressés, alors vous êtes obligé d'inclure le préfixe data/
À peu près quoi qu'il arrive. Vous pouvez utiliser os.path.join('data', 'data.txt)
si vous avez besoin de séparateurs de répertoires alternatifs. En général, je ne trouve aucun problème de compatibilité avec les séparateurs de répertoires de style Unix codés en dur.