os.path
Funciona de una manera divertida. Parece que os
debería ser un paquete con un submódulo path
, pero en realidad os
es un módulo normal que hace magia sys.modules
para inyectar os.path
. Esto es lo que pasa:
Cuando Python se inicia, carga un montón de módulos sys.modules
. No están vinculados a ningún nombre en su script, pero puede acceder a los módulos ya creados cuando los importe de alguna manera.
sys.modules
es un dict en el que los módulos se almacenan en caché. Cuando importa un módulo, si ya se ha importado en alguna parte, se almacena la instancia sys.modules
.
os
se encuentra entre los módulos que se cargan cuando se inicia Python. Asigna su path
atributo a un módulo de ruta específico del sistema operativo.
Se inyecta sys.modules['os.path'] = path
para que pueda " import os.path
" hacer como si fuera un submódulo.
Tiendo a pensar os.path
en un módulo que quiero usar en lugar de una cosa en el os
módulo , por lo que aunque no es realmente un submódulo de un paquete llamado os
, lo importo como si fuera uno y siempre lo hagoimport os.path
. Esto es consistente con cómo os.path
se documenta.
Por cierto, este tipo de estructura conduce a una gran confusión temprana de los programadores de Python sobre módulos y paquetes y organización de código, creo. Esto es realmente por dos razones
Si piensa os
en un paquete y sabe que puede hacer import os
y tener acceso al submódulo os.path
, puede sorprenderse más tarde cuando no pueda hacerlo import twisted
y acceder automáticamente twisted.spread
sin importarlo.
Es confuso que os.name
sea algo normal, una cadena y que os.path
sea un módulo. Siempre estructuro mis paquetes con __init__.py
archivos vacíos para que al mismo nivel siempre tenga un tipo de cosas: un módulo / paquete u otras cosas. Varios grandes proyectos de Python adoptan este enfoque, que tiende a crear un código más estructurado.
import os.path
yo mismo y creo que es una mejor manera. Por "Esto es coherente con la forma en que se documenta os.path" quise decir que se le da su propia página en la documentación en docs.python.org/library/os.path.html .os.py
hecho se inyecta ensys.modules['os.path']
. Entonces esta es la razón por la quefrom os.path import something
realmente funciona. Tenía curiosidad sobre cuándo se introdujo esto y verifiqué la fuente. Dato curioso: esto es de 1999, incluido por primera vez en Python 1.5.2. El compromiso original está aquí .Según PEP-20 de Tim Peters, "explícito es mejor que implícito" y "la legibilidad cuenta". Si todo lo que necesita del
os
módulo está debajoos.path
,import os.path
sería más explícito y dejaría que otros sepan lo que realmente le importa.Del mismo modo, PEP-20 también dice que "lo simple es mejor que lo complejo", por lo que si también necesita cosas que residan bajo el
os
paraguas más general ,import os
sería preferible.fuente
import os
trata realmente de ser "simple" de ninguna manera significativa. Simple! = Corto.import os
yimport os.path
es una tontería si, por ejemplo, necesitasos.getcwd()
yos.path.isfile()
Respuesta definitiva:
import os
y usoos.path
. No lo hagasimport os.path
directamente.De la documentación del módulo en sí:
fuente
os.path
módulo que no existe, sino paraposixpath
."Instead of importing this module directly, import os and refer to this module as os.path."
se encuentra enposixpath.py
(omacpath.py
,ntpath.py
etc.). Estoy bastante seguro de que lo que quieren decir es que uno no deberíaimport posixpath
(lo que funciona), sino más bien importar el módulo a travésos
de una mejor portabilidad. No creo que tengan la intención de dar una recomendación sobre si se prefiereimport os
o noimport os.path
.Curiosamente, importar os.path importará todos los sistemas operativos. intente lo siguiente en el mensaje interactivo:
El resultado será el mismo que si acaba de importar el sistema operativo. Esto se debe a que os.path se referirá a un módulo diferente según el sistema operativo que tenga, por lo que python importará os para determinar qué módulo cargar para la ruta.
referencia
Con algunos módulos, decir
import foo
no expondráfoo.bar
, así que supongo que realmente depende del diseño del módulo específico.En general, solo importar los módulos explícitos que necesita debería ser marginalmente más rápido. En mi máquina
import os.path
:7.54285810068e-06
segundosimport os
:9.21904878972e-06
segundosEstos tiempos son lo suficientemente cercanos como para ser bastante insignificantes. Es posible que su programa necesite usar otros módulos desde
os
ahora o más adelante, por lo que generalmente tiene sentido sacrificar los dos microsegundos y usarimport os
para evitar este error en un momento posterior. Por lo general, me inclino por importar el sistema operativo en su conjunto, pero puedo ver por qué algunos preferiríanimport os.path
ser técnicamente más eficientes y transmitir a los lectores del código que esa es la única parte delos
módulo que deberá usarse. Esencialmente se reduce a una pregunta de estilo en mi mente.fuente
from os import path
hará que las llamadas al camino sean aún más rápidas si la velocidad es el problema.El sentido común funciona aquí:
os
es un módulo y tambiénos.path
es un módulo. Tan solo importe el módulo que desea utilizar:Si desea utilizar funcionalidades en el
os
módulo, importeos
.Si desea utilizar funcionalidades en el
os.path
módulo, importeos.path
.Si desea utilizar funcionalidades en ambos módulos, importe ambos módulos:
Para referencia:
Lib / idlelib / rpc.py utiliza
os
e importaos
.Lib / idlelib / idle.py utiliza
os.path
e importaos.path
.Lib / surepip / init .py usa ambos e importa ambos.
fuente
No se pudo encontrar ninguna referencia definitiva, pero veo que el código de ejemplo para os.walk usa os.path pero solo importa os
fuente