Ne pas utiliser l’opérateur splat dans un import, vous l’avez sans doute lu 100 fois, mais savez-vous pourquoi ?
Regardez la fonction open
:
>>> help(open) open(name[, mode[, buffering]]) -> file object Open a file using the file() type, returns a file object. This is the preferred way to open a file. See file.__doc__ for further information. (END) |
Maintenant, si j’importe le module os
, ça ne change rien :
>>> import os >>> help(open) open(name[, mode[, buffering]]) -> file object Open a file using the file() type, returns a file object. This is the preferred way to open a file. See file.__doc__ for further information. (END) |
Si par contre j’importe tout le contenu du module os
, sans namespace :
>>> from os import * >>> help(open) open(filename, flag [, mode=0777]) -> fd Open a file (for low level IO). (END) |
La différence ?
Dans le premier cas, on a la fonction open()
built-in de Python. Dans le second cas, la fonction os.open()
a été importée et a remplacé la fonction open()
.
Ici le bug sera très difficile à trouver, car les deux fonctions ont presque la même signature :
open(name[, mode[, buffering]]) -> file object
VS
open(filename, flag [, mode=0777]) -> fd
Et en plus un usage très similaire.
Bottom line, import *
, c’est pour les sessions shell. Dans vos fichiers de code, ne l’utilisez pas, vous ne savez pas ce que vous importez.
Ou plus exactement, on sait ce que l’on import mais pas ce que ca peut remplacer dans le deja built (built-in + previous imports), non ? :)
Du coup, quand t’as fait ‘from os import open’, comment tu peu utiliser le open builtin ?
@nainport : personnellement je suis incapable de dire ce que j’importe avec *. Par exemple, avec *, tu importe automatiquement le module sys car os import sys. Donc non seulement tu sais pas ce que tu vas remplacer, mais en plus tu ne sais pas ce que tu déclenches derrière.
@Jean-Eud Tu fais pas
from os import open
. Mais si tu le faisais, tu pourrais trouver le bout de code responsable facilement. Si tu as des import *, pour trouver d’où vient le problème, bonne chance.Pour les imports de la lib standard, on fait presque toujours “import module” de toute façon:
Seuls les modules très spécifiques, avec des noms longs et des fonctions qui ont peu de chance de clasher sont importés avec “from”:
from itertools import chain
from datetime import datetime
Et comme c’est explicite, on sait exactement ce qu’on a dans le namespace si il y a un problème plus tard.
Ne vaut-il pas mieux faire un
import os
et ensuite utiliser os.open() chaque fois qu’on en a besoin ?Ne vaut-il pas mieux lire le commentaire précédent ?
Est ce que vous pourriez éclairer ma lanterne à ce sujet.
Lorsque je dev avec Pygame, je suis obligé de l’importer ainsi :
D’un côté, “.locals”, je ne sais pas du tout à quoi il peut bien servir et d’un autre côté seulement que quasi l’ensemble des programmes utilisant la lib pygame se servent de “from pygame.locals import *”.
@Jean-Eude : dans un tel cas (à ne pas faire), tu peux retrouver le open builtin via
__builtin__.open
@Jean-Eude : si tu utilise “from os import open”, tu ne peux plus utiliser le open builtin, mais si tu fais ça, c’est que :
– tu en es conscient
– tu veux vraiment utiliser la fonction open de os plutôt que la built-in dans tout ton module
@Eric : c’est une mauvaise habitude qui a été prise dans beaucoup de programmes pour toolkit graphic (on voit ça aussi dans pas mal de code avec QT ou Tkinter). Tu vois le problème, tu copies cette ligne et tu ne sais pas du tout ce qu’elle fait. Et moi non plus : impossible de savoir les dépendances du programme. Tu en utilises des composants, et tu ne sais pas d’où ils viennent.
C’est une mauvaise chose, à part dans le cas où tu utilises 20 objets de locals, et ce dans plusieurs fichiers. Ce cas exceptionnel dénote un gros projet et un dev qui sait ce qu’il fait. Dans ce cas le raccourcis est acceptable puisqu’on sait d’où on vient et où on va avec l’expérience, et le bénéfice dépasse le coût.
Mais un tel dev n’aura pas besoin de mon article et ne le lira pas.
Si vraiment tu veux importer open de os et garder le builting open tu peux faire
@Sam Bien vu, merci ! ;)