Dovrei usare `import os.path` o` import os`?


139

Secondo la documentazione ufficiale , os.pathè un modulo. Quindi, qual è il modo preferito di importarlo?

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

O...

# Is importing os enough?
import os

Per favore NON rispondere "importare osopere per me". Lo so, funziona anche per me adesso (a partire da Python 2.6). Quello che voglio sapere è qualsiasi raccomandazione ufficiale su questo problema. Quindi, se rispondi a questa domanda, pubblica i tuoi riferimenti .

Risposte:


157

os.pathfunziona in modo divertente. Sembra che osdovrebbe essere un pacchetto con un sottomodulo path, ma in realtà osè un modulo normale che fa magie sys.modulesper iniettare os.path. Ecco cosa succede:

  • Quando Python si avvia, carica un mucchio di moduli in sys.modules. Non sono associati a nessun nome nel tuo script, ma puoi accedere ai moduli già creati quando li importi in qualche modo.

    • sys.modulesè un dict in cui i moduli sono memorizzati nella cache. Quando si importa un modulo, se è già stato importato da qualche parte, viene archiviata l'istanza sys.modules.
  • osè tra i moduli che vengono caricati all'avvio di Python. Assegna il suo pathattributo a un modulo percorso specifico del sistema operativo.

  • Inietta in sys.modules['os.path'] = pathmodo che tu possa fare " import os.path" come se fosse un sottomodulo.

Tendo a pensare os.pathcome un modulo che voglio usare piuttosto che una cosa nel osmodulo , quindi anche se non è in realtà un sottomodulo di un pacchetto chiamato os, lo importa in un certo senso come è uno e lo faccio sempreimport os.path . Ciò è coerente con come os.pathè documentato.


Per inciso, questo tipo di struttura porta a molta confusione iniziale dei programmatori Python su moduli, pacchetti e organizzazione del codice, credo. Questo è davvero per due motivi

  1. Se pensi osa un pacchetto e sai che puoi fare import ose avere accesso al sottomodulo os.path, potresti essere sorpreso in seguito quando non puoi farlo import twistede accedervi automaticamente twisted.spreadsenza importarlo.

  2. È confuso che os.nameè una cosa normale, una stringa ed os.pathè un modulo. Strutturo sempre i miei pacchetti con __init__.pyfile vuoti in modo che allo stesso livello abbia sempre un tipo di cose: un modulo / pacchetto o altro. Diversi grandi progetti Python adottano questo approccio, che tende a rendere il codice più strutturato.


Risposta eccellente, molto istruttiva! Congratulazioni! Anche se non risponde direttamente alla domanda, ha molti dettagli utili. Ma potresti approfondire "Questo è coerente con come è documentato os.path"? Come ha detto Chris Hulan, l'esempio os.walk () importa solo os anziché os.path.
Denilson Sá Maia,

3
@Dililson, include una risposta diretta: faccio sempre import os.pathme stesso e penso che sia un modo migliore. Con "Questo è coerente con il modo in cui os.path è documentato" Volevo dire che gli è stata data una sua pagina nella documentazione su docs.python.org/library/os.path.html .
Mike Graham,

1
Wow, os.pyinietta davvero sys.modules['os.path']. Ecco perché from os.path import somethingfunziona davvero. Ero curioso di sapere quando è stato introdotto e verificato la fonte. Curiosità: è del 1999, incluso per la prima volta in Python 1.5.2. Il commit originale è qui .
Bluehorn,

29

Secondo PEP-20 di Tim Peters, "Esplicito è meglio di implicito" e "Contabilità della lettura". Se tutto ciò di cui hai bisogno dal osmodulo è sotto os.path, import os.pathsarebbe più esplicito e far sapere agli altri cosa ti interessa davvero.

Allo stesso modo, PEP-20 dice anche "Semplice è meglio che complesso", quindi se hai bisogno anche di cose che risiedono sotto l' osombrello più generale , import ossarebbe preferibile.


2
Non vedo quanto import ossia veramente "semplice" in alcun modo significativo. Semplice! = Breve.
Mike Graham,

14
Stavo più cercando di evidenziarlo import os e uno import os.pathè stupido se ad esempio ne hai bisogno os.getcwd()eos.path.isfile()
Nick T

15

Risposta definitiva: import ose uso os.path. non import os.pathdirettamente.

Dalla documentazione del modulo stesso:

>>> 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).
...

13
Nota che non si tratta di documenti per un os.pathmodulo che non esiste, ma per posixpath.
WRAR

18
Non è affatto per questo che penso che la dottring debba essere interpretata, sebbene sia piuttosto fuorviante. Tieni presente che la frase "Instead of importing this module directly, import os and refer to this module as os.path."si trova in posixpath.py(o macpath.py, ntpath.pyecc.). Sono abbastanza sicuro che ciò che significano è che non si dovrebbe import posixpath(che funziona), ma piuttosto importare il modulo tramite osper una migliore portabilità. Non penso che intendono dare una raccomandazione sul fatto se import oso import os.pathè preferito.
terremoto del

1
Sono d'accordo con la maggior parte del commento di @flornquake ma non sono d'accordo con l'ultima frase. Sia posixpath.py che ntpath.py dicono "import os e si riferiscono a questo modulo come os.path". Non dicono "import os.path e si riferiscono a questo modulo come os.path". macpath.py non ha nulla in proposito.
Pete Forman,

3
Questo è un buon esempio di come un documento che contiene questo puntatore può essere fuorviante: D
Cyker

7

È interessante notare che l'importazione di os.path importerà tutto il sistema operativo. prova quanto segue nel prompt interattivo:

import os.path
dir(os)

Il risultato sarà lo stesso di se hai appena importato os. Questo perché os.path farà riferimento a un modulo diverso in base al sistema operativo in uso, quindi python importerà os per determinare quale modulo caricare per il percorso.

riferimento

Con alcuni moduli, dire import foonon esporrà foo.bar, quindi immagino che dipenda davvero dal design del modulo specifico.


In generale, l'importazione dei moduli espliciti necessari dovrebbe essere leggermente più veloce. Sulla mia macchina:

import os.path: 7.54285810068e-06 secondi

import os: 9.21904878972e-06 secondi

Questi tempi sono abbastanza vicini da essere abbastanza trascurabili. Il tuo programma potrebbe dover utilizzare altri moduli da osora o in un momento successivo, quindi di solito ha senso sacrificare i due microsecondi e utilizzarlo import osper evitare questo errore in un secondo momento. Di solito mi schierò con l'importazione del sistema operativo nel suo insieme, ma posso capire perché alcuni preferirebbero import os.pathessere tecnicamente più efficienti e trasmettere ai lettori del codice che questa è l'unica parte del osmodulo che dovrà essere utilizzata. In sostanza si riduce a una domanda di stile nella mia mente.


2
from os import pathrenderà le chiamate al percorso ancora più veloci se la velocità è il problema.
Justin Peel,

Essendo pitonico, esplicito è meglio di implicito giusto? In realtà penso che sia davvero la chiamata di giudizio da parte dell'utente, se l'utente utilizzerà solo os.path o più moduli all'interno di os. Forse un metodo è più in linea con la tua filosofia rispetto all'altro?
Andrew Kou,

23
Il tempismo è una delle ottimizzazioni premature più premature che abbia mai visto. Questo non è mai stato il collo di bottiglia di nessuno e il tempo qui è irrilevante per come qualcuno dovrebbe programmare.
Mike Graham,

5

Il buon senso funziona qui: osè un modulo ed os.pathè anche un modulo. Quindi basta importare il modulo che si desidera utilizzare:

  • Se si desidera utilizzare funzionalità nel osmodulo, quindi importare os.

  • Se si desidera utilizzare funzionalità nel os.pathmodulo, quindi importare os.path.

  • Se si desidera utilizzare le funzionalità in entrambi i moduli, importare entrambi i moduli:

    import os
    import os.path

Per riferimento:


4

Impossibile trovare alcun riferimento definitivo, ma vedo che il codice di esempio per os.walk utilizza os.path ma importa solo os

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.