2010-04-27 26 views
103

Según el official documentation, os.path es un módulo. Por lo tanto, ¿cuál es la forma preferida de importarlo?¿Debo usar `import os.path` o` import os`?

# Should I always import it explicitly? 
import os.path 

O ...

# Is importing os enough? 
import os 

Por favor, no responder a la "importación os funciona para mí". Lo sé, también funciona para mí en este momento (a partir de Python 2.6). Lo que quiero saber es cualquier recomendación oficial sobre este tema. Por lo tanto, si responde esta pregunta, por favor publique sus referencias.

Respuesta

121

os.path funciona de una manera divertida.Parece que os debe ser un paquete con un submódulo path, pero en realidad os es un módulo normal que hace magia con sys.modules para inyectar os.path. Esto es lo que sucede:

  • Cuando Python se pone en marcha, se carga un montón de módulos en sys.modules. No están vinculados a ningún nombre en su secuencia de comandos, pero puede acceder a los módulos ya creados cuando los importa de alguna manera.

    • sys.modules es un dict en el que los módulos están en caché. Cuando importa un módulo, si ya se ha importado en algún lugar, obtiene la instancia almacenada en sys.modules.
  • os es uno de los módulos que se cargan cuando se inicia Python. Asigna su atributo path a un módulo de ruta específico del sistema operativo.

  • Se inyecta sys.modules['os.path'] = path para que pueda hacer "import os.path" como si fuera un submódulo.

tiendo a pensar en os.path como un módulo Quiero usar en lugar de una cosa en el módulo os, por lo que aunque no es realmente un submódulo de un paquete llamado os, me importarlo como si fuera uno y siempre hago import os.path. Esto es coherente con la forma en que se documenta os.path.


Por cierto, este tipo de estructura da lugar a una gran confusión temprana Python programadores acerca de los módulos y paquetes y organización del código, creo. Esto es realmente por dos razones

  1. Si se piensa en os como un paquete y saber que se puede hacer import os y tener acceso al submódulo os.path, usted puede ser sorprendido más tarde, cuando no se puede hacer de forma automática y import twisted acceda al twisted.spread sin importarlo.

  2. Es confuso que os.name es una cosa normal, una cadena y os.path es un módulo. Siempre estructuro mis paquetes con archivos __init__.py vacíos, de modo que en el mismo nivel siempre tengo un tipo de cosas: un módulo/paquete u otras cosas. Varios grandes proyectos de Python toman este enfoque, que tiende a hacer un código más estructurado.

+0

¡Excelente respuesta, muy informativa! ¡Felicitaciones! Aunque no responde directamente la pregunta, tiene muchos detalles útiles. Pero, ¿podría explicar más detalladamente "esto es coherente con la forma en que se documenta os.path"? Al igual que Chris Hulan, el ejemplo os.walk() importa solo el sistema operativo en lugar de os.path. –

+3

@Denilson, incluye una respuesta directa: siempre hago 'import os.path' y creo que es una manera más agradable. Por "Esto es coherente con la forma en que se documenta os.path" Quise decir que se le dio su propia página en la documentación en http://docs.python.org/library/os.path.html. –

+0

¿Por qué? ¿Por qué se hace de esta manera? – user1712447

6

Curiosamente, la importación de os.path importará todos los sistemas operativos. intente lo siguiente en el indicador interactivo:

import os.path 
dir(os) 

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á el sistema operativo para determinar qué módulo cargar para la ruta.

reference

Con algunos módulos, diciendo import foo no expondrá foo.bar, así que supongo que realmente depende del diseño del módulo específico.


En general, la importación de los módulos explícitos que necesita debe ser un poco más rápida. En mi máquina:

import os.path:7.54285810068e-06 segundo

import os:9.21904878972e-06 segundo

Estos tiempos son lo suficientemente cerca para ser bastante insignificante. Su programa puede necesitar usar otros módulos desde os ahora o en un momento posterior, por lo que tiene sentido sacrificar los microsegundos y usar import os para evitar este error más adelante. Normalmente me limito a importar solo os como un todo, pero puedo ver por qué algunos prefieren import os.path para ser técnicamente más eficientes y transmitir a los lectores del código que esa es la única parte del módulo os que será necesario usar. Básicamente se reduce a una pregunta de estilo en mi mente.

+2

'path' de importación os hará que las llamadas a la ruta aún más rápido si la velocidad es el problema –

+0

Ser pythonic, explícito es mejor que implícito ¿verdad? En realidad, creo que realmente es la decisión del usuario, ya sea que el usuario solo use os.path o varios módulos dentro de os. ¿Tal vez un método está más en línea con su filosofía sobre el otro? –

+14

Temporización esta es una de las optimizaciones prematuras más prematuras que he visto. Esto nunca ha sido * el cuello de botella de nadie * y el tiempo aquí no tiene importancia en cómo alguien debe codificar. –

4

No hemos encontrado ninguna referencia definitiva, pero veo que el código de ejemplo para os.walk utiliza os.path pero sólo importa OS

27

Según PEP-20 por Tim Peters, "Explícito es mejor que implícito" y "La legibilidad cuenta ". Si todo lo que necesita del módulo os es os.path, import os.path sería más explícito y les haría saber a los demás lo que realmente le importa.

Del mismo modo, PEP-20 también dice "Simple es mejor que complejo", por lo que si también necesita cosas que residan bajo el paraguas más general os, sería preferible import os.

+2

No veo cómo 'import os' se trata realmente de ser" simple "de ninguna manera significativa. Simple! = Corto. –

+10

Estaba tratando de señalar que 'import os' ** y ** a' import os.path' son tontos si p. Ej. necesita 'os.getcwd()' y 'os.path.isfile()' –

14

respuesta definitiva: import os y utilizar os.path. no import os.path directamente.

De la documentación del propio módulo:

>>> import os 
>>> help(os.path) 
... 
Instead of importing this module directly, import os and refer to 
this module as os.path. The "os.path" name is an alias for this 
module on Posix systems; on other systems (e.g. Mac, Windows), 
os.path provides the same operations in a manner specific to that 
platform, and is an alias to another module (e.g. macpath, ntpath). 
... 
+7

Tenga en cuenta que no es un documento para un módulo 'os.path' que no existe, sino para' posixpath'. – wRAR

+8

Eso no es en absoluto como creo que la docstring debe interpretarse, aunque es bastante engañosa. Tenga en cuenta que la frase '" en lugar de importar este módulo directamente, importe el sistema operativo y consulte este módulo como os.path. '' Se encuentra en 'posixpath.py' (o' macpath.py', 'ntpath.py 'etc.). Estoy bastante seguro de que lo que quieren decir es que uno no debe 'importar posixpath' (que funciona), sino más bien importar el módulo a través de' os' para una mejor portabilidad. No creo que tengan la intención de dar una recomendación sobre si se prefiere 'import os' o' import os.path'. – flornquake

+1

Estoy de acuerdo con la mayoría de los comentarios de @flornquake, pero no estoy de acuerdo con la última oración. Tanto posixpath.py como ntpath.py dicen "import os y se refieren a este módulo como os.path". No dicen "import os.path y se refieren a este módulo como os.path". macpath.py no tiene nada al respecto. –

0

Estoy de acuerdo con Mike

creo

import os está muy bien.

Sólo entonces tiene que mencionar detalles como este

os.path() 

o si está llamando a un módulo dentro de un módulo

os.path.exists()