Cómo hacer referencia a rutas relativas de recursos cuando se trabaja con un repositorio de código en Python


Estamos trabajando con un repositorio de código que se implementa tanto en Windows como en Linux, a veces en directorios diferentes. ¿Cómo debería uno de los módulos dentro del proyecto referirse a uno de los recursos que no son de Python en el proyecto (archivos CSV, etc.)?

Si hacemos algo como:

thefile=open('test.csv')

O:

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

Solo funcionará cuando el script se ejecute desde un directorio específico, o desde un subconjunto de los directorios.

Lo que me gustaría hacer es algo como:

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

Es este el camino correcto? Es posible?

Author: alex, 2009-08-13

7 answers

Intente usar un nombre de archivo relativo a la ruta de los archivos actuales. Ejemplo para './my_file':

fn = os.path.join(os.path.dirname(__file__), 'my_file')
 205
Author: c089,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-13 09:27:28

Si está utilizando herramientas de configuración o distribuir (a setup.py install) entonces la forma" correcta " de acceder a estos recursos empaquetados parece estar usando package_resources.

En su caso, el ejemplo sería

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

Que por supuesto lee el recurso y los datos binarios leídos sería el valor de my_data

Si solo necesita el nombre del archivo, también puede usar

resource_filename(package_or_requirement, resource_name)

Ejemplo:

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

La ventaja es que su garantizado para trabajar incluso si es un archivo distribución como un huevo.

Véase http://packages.python.org/distribute/pkg_resources.html#resourcemanager-api

 32
Author: Sharoon Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-07 14:24:07

A menudo uso algo similar a esto:

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__

Contiene el nombre de archivo del script en el que escribe ese código, por lo que puede crear rutas relativas al script, pero todavía escritas con rutas absolutas. Funciona bastante bien, por varias razones:

  • el camino es absoluto, pero sigue siendo relativo
  • el proyecto todavía se puede desplegar en un contenedor relativo

Pero debe estar atento a la compatibilidad de la plataforma: el sistema operativo Windows.pathsep es diferente a UNIX.

 11
Author: user137673,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-13 12:11:19
import os
cwd = os.getcwd()
path = os.path.join(cwd, "my_file")
f = open(path)

También intenta normalizar tu cwd usando os.path.abspath(os.getcwd()). Más información aquí .

 7
Author: gavoja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-08-13 09:40:27

En Python, las rutas son relativas a la directorio de trabajo actual, que en la mayoría de los casos es el directorio desde el que se ejecuta el programa. El directorio de trabajo actual es muy probable que no sea el mismo que el directorio de su archivo de módulo, por lo que usar una ruta relativa a su archivo de módulo actual siempre es una mala elección.

Usar ruta absoluta debería ser la mejor solución:

import os
package_dir = os.path.dirname(os.path.abspath(__file__))
thefile = os.path.join(package_dir,'test.cvs')
 7
Author: skyfree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-27 08:43:47

Puede usar la variable build in __file__. Contiene la ruta del archivo actual. Implementaría getBaseOfProject en un módulo en la raíz de tu proyecto. Allí obtendría la parte del camino de __file__ y devolvería eso. Este método se puede usar en cualquier parte del proyecto.

 2
Author: Achim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-04 16:28:56

Pasé mucho tiempo averiguando la respuesta a esto, pero finalmente lo conseguí (y en realidad es muy simple):

import sys
import os
sys.path.append(os.getcwd() + '/your/subfolder/of/choice')

# now import whatever other modules you want, both the standard ones,
# as the ones supplied in your subfolders

Esto agregará la ruta relativa de su subcarpeta a los directorios en los que Python debe buscar Es bastante rápido y sucio, pero funciona como un encanto :)

 -1
Author: Rutger Semp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-02 12:43:48