os.path
fonctionne d'une manière amusante. Cela ressemble à os
un package avec un sous-module path
, mais en réalité, os
c'est un module normal qui fait de la magie sys.modules
pour injecter os.path
. Voici ce qui se passe:
Lorsque Python démarre, il charge un tas de modules dans sys.modules
. Ils ne sont liés à aucun nom dans votre script, mais vous pouvez accéder aux modules déjà créés lorsque vous les importez d'une manière ou d'une autre.
sys.modules
est un dict dans lequel les modules sont mis en cache. Lorsque vous importez un module, s'il a déjà été importé quelque part, il obtient l'instance stockée dans sys.modules
.
os
fait partie des modules chargés au démarrage de Python. Il affecte son path
attribut à un module de chemin spécifique au système d'exploitation.
Il injecte de sys.modules['os.path'] = path
sorte que vous puissiez faire " import os.path
" comme s'il s'agissait d'un sous-module.
J'ai tendance à penser os.path
à un module que je veux utiliser plutôt qu'à une chose dans le os
module , donc même si ce n'est pas vraiment un sous-module d'un package appelé os
, je l'importe un peu comme si c'était un et je le fais toujoursimport os.path
. Ceci est cohérent avec la façon dont os.path
est documenté.
Incidemment, ce type de structure conduit à beaucoup de confusion précoce des programmeurs Python sur les modules et les packages et l'organisation du code, je pense. C'est vraiment pour deux raisons
Si vous pensez os
à un package et que vous savez que vous pouvez faire import os
et avoir accès au sous-module os.path
, vous pourriez être surpris plus tard de ne pas pouvoir le faire import twisted
et y accéder automatiquement twisted.spread
sans l'importer.
Il est déroutant que ce os.name
soit une chose normale, une chaîne et os.path
un module. Je structure toujours mes packages avec des __init__.py
fichiers vides de sorte qu'au même niveau j'ai toujours un type de chose: un module / package ou autre. Plusieurs grands projets Python adoptent cette approche, qui tend à rendre le code plus structuré.
import os.path
moi - même et je pense que c'est une meilleure façon. Par "Ceci est cohérent avec la façon dont os.path est documenté", je voulais dire qu'il a sa propre page dans la documentation à docs.python.org/library/os.path.html .os.py
injecte en effet danssys.modules['os.path']
. Voilà pourquoifrom os.path import something
fonctionne réellement. J'étais curieux de savoir quand cela a été introduit et j'ai vérifié la source. Fait amusant: il s'agit de 1999, initialement inclus dans Python 1.5.2. Le commit original est ici .Selon PEP-20 de Tim Peters, «l'explicite est meilleur que l'implicite» et «la lisibilité compte». Si tout ce dont vous avez besoin du
os
module est sousos.path
,import os.path
serait plus explicite et laisser les autres savoir ce qui vous tient vraiment à cœur.De même, PEP-20 dit également "Simple est mieux que complexe", donc si vous avez également besoin de choses qui se trouvent sous le
os
parapluie plus général , ilimport os
serait préférable.la source
import os
consiste vraiment à être «simple» d'une manière significative. Simple! = Court.import os
et unimport os.path
est daft par exemple si vous besoinos.getcwd()
etos.path.isfile()
Réponse définitive:
import os
et utilisationos.path
. pasimport os.path
directement.Depuis la documentation du module lui-même:
la source
os.path
module qui n'existe pas, mais pourposixpath
."Instead of importing this module directly, import os and refer to this module as os.path."
se trouve dansposixpath.py
(oumacpath.py
,ntpath.py
etc.). Je suis assez sûr que ce qu'ils veulent dire, c'est qu'il ne faut pasimport posixpath
(ce qui fonctionne), mais plutôt importer le module viaos
pour une meilleure portabilité. Je ne pense pas qu'ils aient l'intention de faire une recommandation sur l'opportunitéimport os
ou laimport os.path
préférence.Il est intéressant de noter que l'importation de os.path importera tous les fichiers os. essayez ce qui suit dans l'invite interactive:
Le résultat sera le même que si vous venez d'importer os. C'est parce que os.path fera référence à un module différent en fonction du système d'exploitation que vous avez, donc python importera os pour déterminer quel module charger pour le chemin.
référence
Avec certains modules, dire
import foo
ne sera pas exposéfoo.bar
, donc je suppose que cela dépend vraiment de la conception du module spécifique.En général, importer simplement les modules explicites dont vous avez besoin devrait être légèrement plus rapide. Sur ma machine:
import os.path
:7.54285810068e-06
secondesimport os
:9.21904878972e-06
secondesCes temps sont suffisamment proches pour être assez négligeables. Votre programme peut avoir besoin d'utiliser d'autres modules à partir de
os
maintenant ou plus tard, il est donc généralement logique de simplement sacrifier les deux microsecondes et de les utiliserimport os
pour éviter cette erreur plus tard. Je suis généralement d'accord avec l'importation d'os dans son ensemble, mais je peux voir pourquoi certains préféreraientimport os.path
être techniquement plus efficaces et transmettre aux lecteurs du code que c'est la seule partie duos
module qui devra être utilisée. Cela se résume essentiellement à une question de style dans mon esprit.la source
from os import path
rendra les appels au chemin encore plus rapides si la vitesse est le problème.Le bon sens fonctionne ici:
os
est un module, etos.path
est aussi un module. Alors importez simplement le module que vous souhaitez utiliser:Si vous souhaitez utiliser les fonctionnalités du
os
module, importezos
.Si vous souhaitez utiliser les fonctionnalités du
os.path
module, importezos.path
.Si vous souhaitez utiliser des fonctionnalités dans les deux modules, importez les deux modules:
Pour référence:
Lib / idlelib / rpc.py utilise
os
et importeos
.Lib / idlelib / idle.py utilise
os.path
et importeos.path
.Lib / ensurepip / init .py utilise les deux et importe les deux.
la source
Impossible de trouver une référence définitive, mais je vois que l'exemple de code pour os.walk utilise os.path mais importe seulement os
la source