¿Cómo importo un módulo de Python dada su ruta relativa?
Por ejemplo, si dirFoo
contiene Foo.py
y dirBar
, y dirBar
contiene Bar.py
, ¿Cómo se importan Bar.py
en Foo.py
?
Aquí hay una representación visual:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
desea incluir Bar
, pero la reestructuración de la jerarquía de carpetas no es una opción.
python
relative-path
python-import
Jude Allred
fuente
fuente
Respuestas:
Suponiendo que ambos directorios son paquetes reales de Python (sí tienen el
__init__.py
archivo dentro de ellos), aquí hay una solución segura para incluir módulos en relación con la ubicación del script.Supongo que quiere hacer esto, porque necesita incluir un conjunto de módulos con su script. Lo uso en producción en varios productos y funciona en muchos escenarios especiales como: scripts llamados desde otro directorio o ejecutados con Python execute en lugar de abrir un nuevo intérprete.
Como beneficio adicional, este enfoque le permite forzar a Python a usar su módulo en lugar de los instalados en el sistema.
¡Advertencia! Realmente no sé qué sucede cuando el módulo actual está dentro de un
egg
archivo. Probablemente también falla.fuente
os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")
Do NO añadir la subcarpeta antes deabspath
que esto provoca fallos graves.cmd_subfolder
) directamente a mi respuesta. ¡Gracias!realpath
ya genera caminos absolutos, por lo tanto no los necesitoabspath
. Tambiénos.path.dirname
se puede usar en lugar de dividir, haciendo que la indexación quede[0]
obsoleta. La línea sería:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Asegúrese de que dirBar tenga el
__init__.py
archivo; esto convierte un directorio en un paquete de Python.fuente
sys.path
entonces la presencia de__init__.py
en eldirBar
directorio no ayuda mucho.__init.py__
solo funcionará cuando el directorio ya esté en sys.path y en mi caso no lo estaba. La solución de "sorin" (aceptada) siempre funciona.sys.path
la pregunta? ¿Quizás hubo algo omitido que no vimos ni supimos?También puede agregar el subdirectorio a su ruta de Python para que se importe como un script normal.
fuente
sys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
sys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
sys.path.insert(0, <path to dirFoo>)
ya que cargará este módulo antes que los módulos del mismo nombre almacenados en otro lugar.fuente
os.path.join()
lugar de unirse por '/', que se romperá en las ventanas (cojo).os.path.abspath(os.path.join(__file__,'..','lib'))
?Simplemente haga cosas simples para importar el archivo .py desde una carpeta diferente.
Digamos que tiene un directorio como:
Luego, solo mantenga un archivo vacío en la carpeta lib como se llama
Y luego usar
Mantenga el
__init__.py
archivo en cada carpeta de la jerarquía del módulo de importación.fuente
Si estructura su proyecto de esta manera:
Luego, desde Foo.py deberías poder hacer:
O:
Según el comentario de Tom, esto requiere que se
src
pueda acceder a la carpeta a través desite_packages
su ruta de búsqueda. Además, como él menciona,__init__.py
se importa implícitamente cuando se importa por primera vez un módulo en ese paquete / directorio. Típicamente__init__.py
es simplemente un archivo vacío.fuente
from dirFoo import Foo
decirFoo.bla()
. Si usarimport dirFoo.Foo
uno debería usardirFoo.Foo.bla()
, bastante feo incluso sin la funda de camello.El método más fácil es usar sys.path.append ().
Sin embargo, también te puede interesar el módulo imp . Proporciona acceso a funciones de importación internas.
Esto se puede usar para cargar módulos dinámicamente cuando no conoce el nombre de un módulo.
Lo he usado en el pasado para crear una interfaz de tipo plugin para una aplicación, donde el usuario escribiría un script con funciones específicas de la aplicación, y simplemente colocaría su script en un directorio específico.
Además, estas funciones pueden ser útiles:
fuente
Esta es la PEP relevante:
http://www.python.org/dev/peps/pep-0328/
En particular, suponiendo que dirFoo es un directorio desde dirBar ...
En dirFoo \ Foo.py:
fuente
La forma más fácil sin ninguna modificación en su script es establecer la variable de entorno PYTHONPATH. Debido a que sys.path se inicializa desde estas ubicaciones:
Solo corre:
Su sys.path contiene la ruta anterior, como se muestra a continuación:
fuente
En mi opinión, la mejor opción es poner __ init __.py en la carpeta y llamar al archivo con
No se recomienda usar sys.path.append () porque algo podría salir mal si usa el mismo nombre de archivo que el paquete python existente. No he probado eso, pero será ambiguo.
fuente
from dirBar.Bar import *
funciona, pero nofrom dirBar.Bar import Bar
. ¿Sabes por qué * funciona? ¿Qué pasaría si tuviera varios archivos en dirBar / y quisiera obtener solo algunos de ellos (usando un método como el que ha publicado aquí)?from dirBar import Bar
.from
indica la fuente, y todoimport
lo que sigue es qué tomar de esa fuente.from dirBar.Bar import Bar
significa "Desde la fuente, importe la fuente en sí", lo que no tiene sentido. los*
medios sin embargo, "me dan todo, desde la fuente"La manera rápida y sucia para los usuarios de Linux
Si solo está jugando y no le importan los problemas de implementación, puede usar un enlace simbólico (suponiendo que su sistema de archivos lo admita) para hacer que el módulo o paquete sea directamente visible en la carpeta del módulo solicitante.
o
Nota: Un "módulo" es cualquier archivo con una extensión .py y un "paquete" es cualquier carpeta que contiene el archivo
__init__.py
(que puede ser un archivo vacío). Desde el punto de vista del uso, los módulos y los paquetes son idénticos: ambos exponen sus "definiciones y declaraciones" contenidas según lo solicitado a través delimport
comando.Ver: http://docs.python.org/2/tutorial/modules.html
fuente
en vez de:
por si acaso podría haber otro dirBar instalado y confundir a un lector foo.py.
fuente
Para este caso para importar Bar.py en Foo.py, primero convertiría estas carpetas en paquetes de Python de esta manera:
Entonces lo haría así en Foo.py:
Si quisiera que el espacio de nombres se pareciera a Bar. lo que sea , o
Si quisiera el espacio de nombres dirBar.Bar. lo que sea . Este segundo caso es útil si tiene más módulos bajo el paquete dirBar.
fuente
Agregue un archivo __init__.py :
Luego agregue este código al inicio de Foo.py:
fuente
dirBar
ya es un paquete de Python (por la existencia dedirBar/__init__.py
), no hay necesidad de añadirdirBar
asys.path
, ¿no? La declaraciónimport Bar
deFoo.py
debería ser suficiente.Ejemplo relativo de sys.path:
Basado en esta respuesta.
fuente
Bueno, como usted menciona, generalmente desea tener acceso a una carpeta con sus módulos en relación con el lugar donde se ejecuta su script principal, por lo que solo debe importarlos.
Solución:
Tengo el script
D:/Books/MyBooks.py
y algunos módulos (como oldies.py). Necesito importar desde el subdirectorioD:/Books/includes
:Coloque una
print('done')
enoldies.py
, por lo que comprobar que todo va bien. De esta manera, siempre funciona porque, según la definición de Pythonsys.path
inicializada al iniciar el programa, el primer elemento de esta lista,path[0]
es el directorio que contiene el script que se utilizó para invocar al intérprete de Python.Si el directorio del script no está disponible (por ejemplo, si el intérprete se invoca de forma interactiva o si el script se lee desde la entrada estándar),
path[0]
es la cadena vacía, que dirige a Python a buscar primero los módulos en el directorio actual. Observe que el directorio del script se inserta antes de las entradas insertadas como resultado dePYTHONPATH
.fuente
site.addsitedir(sys.path[0]+'/includes')
) en mi primer programa simple de Python break_time.py: https://github.com/ltfschoen/PythonTest . Uso el sistema: MacOS v10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9Simplemente puedes usar:
from Desktop.filename import something
Ejemplo:
el código:
Pero asegúrese de hacer un archivo vacío llamado "
__init__.py
" en ese directoriofuente
import something
luego dije para que sea más fácil*
, básicamente, no es bueno para la memoria RAM y también si 2 funciones tiene el mismo nombre que lo hará en masa de su códigoOtra solución sería instalar el paquete py-require y luego usar lo siguiente en
Foo.py
fuente
require()
función, puede echar un vistazo a mi proyecto Node.pyAquí hay una manera de importar un archivo desde un nivel superior, utilizando la ruta relativa.
Básicamente, simplemente mueva el directorio de trabajo hacia arriba un nivel (o cualquier ubicación relativa), agréguelo a su ruta, luego mueva el directorio de trabajo donde comenzó.
fuente
No tengo experiencia con Python, así que si hay algún error en mis palabras, solo dígame. Si su jerarquía de archivos se organizó así:
module_1.py
define una función llamadafunc_1()
, module_2.py :y ejecuta
python module_2.py
en cmd, ejecutará lo quefunc_1()
define. Así es como importamos los mismos archivos de jerarquía. Pero cuando se escribefrom .module_1 import func_1
enmodule_2.py
, intérprete de python diráNo module named '__main__.module_1'; '__main__' is not a package
. Entonces, para solucionar esto, simplemente conservamos el cambio que acabamos de hacer, y movemos ambos módulos a un paquete, y hacemos que se ejecute un tercer módulo como llamadormodule_2.py
.main.py :
Pero la razón por la que agregamos un
.
antesmodule_1
enmodule_2.py
es que si no hacemos eso y corremosmain.py
, el intérprete de Python diráNo module named 'module_1'
, eso es un poco complicado,module_1.py
está justo al ladomodule_2.py
. Ahora dejofunc_1()
enmodule_1.py
algo Do:que
__name__
registra quién llama a func_1. Ahora guardamos el.
antesmodule_1
, corremain.py
, se imprimirápackage_1.module_1
, nomodule_1
. Indica que quien llamafunc_1()
está en la misma jerarquía quemain.py
, lo.
que implica quemodule_1
está en la misma jerarquía que élmodule_2.py
mismo. Entonces, si no hay un punto,main.py
reconocerámodule_1
en la misma jerarquía que sí mismo, puede reconocerpackage_1
, pero no qué "debajo" de él.Ahora hagámoslo un poco complicado. Tiene un
config.ini
y un módulo define una función para leerlo en la misma jerarquía que 'main.py'.Y por alguna razón inevitable, debe llamarlo
module_2.py
, por lo que debe importar desde la jerarquía superior. module_2.py :Dos puntos significa importar desde la jerarquía superior (acceso de tres puntos superior a superior, etc.). Ahora corremos
main.py
, el intérprete dirá:ValueError:attempted relative import beyond top-level package
. El "paquete de nivel superior" aquí esmain.py
. Solo porqueconfig.py
está al ladomain.py
, están en la misma jerarquía,config.py
no están "debajo"main.py
o no están "guiados"main.py
, por lo que está más allámain.py
. Para solucionar esto, la forma más simple es:Creo que eso coincide con el principio de organizar la jerarquía de archivos del proyecto, debe organizar los módulos con diferentes funciones en diferentes carpetas, y simplemente dejar una llamada superior en el exterior, y puede importar lo que quiera.
fuente
Esto también funciona, y es mucho más simple que cualquier cosa con el
sys
módulo:fuente
Llámame demasiado cauteloso, pero me gusta hacer que el mío sea más portátil porque no es seguro asumir que los archivos siempre estarán en el mismo lugar en cada computadora. Personalmente, el código busca primero la ruta del archivo. Yo uso Linux para que el mío se vea así:
Eso es, por supuesto, a menos que planee agruparlos. Pero si ese es el caso, realmente no necesita dos archivos separados de todos modos.
fuente