IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Est-ce que déclarer un import quand on en a besoin est une optimisation ?


Sujet :

Python

  1. #1
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 419
    Points : 874
    Points
    874
    Par défaut Est-ce que déclarer un import quand on en a besoin est une optimisation ?
    bonjour,


    Vaut-il mieux déclarer un import (import string par exemple) tout le temps tout en haut du fichier .py ou bien quand on en a juste besoin (par exemple dans une fonction ou dans une boucle if )

    qu'en pensez-vous ?

    y-a-t-il des coups supplémentaires à cela ?

  2. #2
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    ben... Si vous en avais besoin autant l'importer. Non ?
    Le coût ? La lecture d'un fichier. Suivant le module cela pourrais être lourd.
    Une contre-indication ?, La portée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Foo:
         def __init__(self):
            import os
            print(locals())
     
    f = Foo()
    print(globals(), locals())
    Une indication ? La compatibilité du code ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    class ScreenCap(object):
        def __init__(self):
            """Screenshot class"""
            if sys.platform == 'linux2':
                self.grab = self._GarbLinux
            elif sys.platform == 'win32':
                import Image, ImageGrab
                self.grab = self._GrabWin
            elif sys.platform == 'darwin':
                self.grab = self._GrabMac
            else:
                sys.exit(1)
            self._currentf = None
     
        def _FicNormalyze(self, name):
            """Internal Function for generate temp file.
               Use home user directory for rights.
            """
            if name:
                if os.path.basename(name) == name:
                    _grabfile = os.path.join(os.path.expanduser('~'), name)
                else:
                    _grabfile = name
            else:
                # default name
                _grabfile = os.path.join(os.path.expanduser('~'), 'scrcap.jpg')
            self._currentf = _grabfile
            return _grabfile
     
        def _GarbLinux(self, name=None):
            """Internal function for screen capture under Linux
               Use ImageMagick import utility
            """
            _grabfile = self._FicNormalyze(name)
            _grabcommand = "import -silent -window root " + _grabfile
            os.system(_grabcommand)
            return _grabfile
     
        def _GrabWin(self, name=None):
            """Internal function for screen capture under Windows.
               Use PIL ImageGrab.
            """
            try:
                import ImageGrab
            except:
                # Experimental import for PIL under Python 3.
                from PIL import ImageGrab
            _grabfile = self._FicNormalyze(name)
            ImageGrab.grab().save(_grabfile, "JPEG")
            return _grabfile
     
        def _GrabMac(self, name=None):
            """Internal function for screen capture under Mac.
               Use screencapture command.
            """
            _grabfile = self._FicNormalyze(name)
            _grabcommand = "screencapture -m -x -t jpg " + _grabfile
            os.system(_grabcommand)
            return _grabfile
    ...
    @+

    Note pour ce qui est de l'import dans une fonction: Les variables locales sont mises en place lors de l'interprétation du code.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> def foo():
    ...     from os import *
    ... 
    <stdin>:1: SyntaxWarning: import * only allowed at module level
    The from form with * may only occur in a module scope. If the wild card form of import — import * — is used in a function and the function contains or is a nested block with free variables, the compiler will raise a SyntaxError.
    Il est assez rare que des 'protections' soit mise en place pour le souligner

  3. #3
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Bonjour.

    Il me semble qu'il vaut mieux toujours indiquer les imports en début de script. C'est pour moi une bonne pratique à suivre à la lettre.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 297
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 297
    Points : 36 794
    Points
    36 794
    Par défaut
    Salut,

    Citation Envoyé par rambc Voir le message
    Il me semble qu'il vaut mieux toujours indiquer les imports en début de script. C'est pour moi une bonne pratique à suivre à la lettre.
    Par défaut, c'est préférable.

    N'empêche qu'au plus le programme est gros au plus il contiendra de fonctions utilisées dans des cas assez particuliers qui pourront se retrouver en tas dans un script.

    Mettre les import dans le "block" permet de documenter ces codes et de faciliter leur réorganisation.

    Côté maintenabilité et optimisation la question peut se poser, mais les réponses sont toujours discutables car le "contexte" n'est jamais "clair".

    - W

  5. #5
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 889
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 889
    Points : 7 241
    Points
    7 241
    Par défaut
    La réponse est dans la PEP 8

    Citation Envoyé par PEP 8
    Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 297
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 297
    Points : 36 794
    Points
    36 794
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    La réponse est dans la PEP 8
    PEP 8 définit des recommandations applicables aux modules de la "Python Standard Library" et aux codes de l'interpréteur Python.
    Les autres programmeurs Python peuvent l'utiliser pour "standardiser" leurs codes ou s'appliquer à suivre d'autres "standards".

    note: l'intérêt de ce type de "standard" est comme celui d'une FAQ, avoir des réponses "good enough" applicables à des questions de bases évitant de refaire des réunions/discussions sans fin à chaque fois.

    Ceci dit, des recommandations n'ont pas force de "lois".
    Et des dimensions optimisation et maintenabilité peuvent donner lieu à ne pas appliquer une recommandation de façon bête. Ce qui suppose pouvoir motiver le "pourquoi" procéder différemment dans certains cas.

    - W

  7. #7
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 889
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 889
    Points : 7 241
    Points
    7 241
    Par défaut
    On a toujours la liberté de coder comme on le souhaite sous certaines réserves évidemment, mais il me semblait clair de l'indiquer car le mot clé always est dans cette phrase plutôt affirmative.

    Personnellement il est très rare de se "prendre la tête" sur le fait d'importer un module à un endroit spécifique, l'optimisation d'un code ne se faisant pas à cet endroit.

  8. #8
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    N'empêche qu'au plus le programme est gros au plus il contiendra de fonctions utilisées dans des cas assez particuliers qui pourront se retrouver en tas dans un script.
    Dans ce cas, j'aurais tendance à casser le script en plusieurs morceaux, cela me parait bien plus efficace côté maintenance : un script --> "une" fonctionnalité --> une liste de modules à importer.

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 297
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 297
    Points : 36 794
    Points
    36 794
    Par défaut
    Salut,

    Citation Envoyé par fred1599 Voir le message
    On a toujours la liberté de coder comme on le souhaite sous certaines réserves évidemment, mais il me semblait clair de l'indiquer car le mot clé always est dans cette phrase plutôt affirmative.
    "always" s'applique aux codeurs/mainteneurs des modules de la PSL. Etes vous l'un d'entre-eux?
    Plus généralement, s'il fallait s'"interdire" de pourquoi laisser le langage permettre de... et dans quels cas utiliser cette fonctionnalités?

    Personnellement il est très rare de se "prendre la tête" sur le fait d'importer un module à un endroit spécifque, l'optimisation d'un code ne se faisant pas à cet endroit.
    Allez lire ce code ou la discussion sur les lazy import dans le wiki Python.

    Dans certains cas, il faut se poser des questions et baliser le chemin qui permettra de construire les réponses.
    - W

  10. #10
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 889
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 889
    Points : 7 241
    Points
    7 241
    Par défaut
    @Wiztricks

    Le code donné en exemple respecte tout à fait la PEP 8, ou j'ai mal vu?

    Les exemples concernant les lazy imports, justifie clairement une pénalité du temps d'exécution en cas de non respect de la PEP 8, il me semble, non?

    En fait quelle serait la bonne raison d'importer un module en dehors du début d'un fichier?

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 297
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 297
    Points : 36 794
    Points
    36 794
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Le code donné en exemple respecte tout à fait la PEP 8, ou j'ai mal vu?
    Il effectue des "import" à l'intérieur de blocs et non en tête de...
    De plus, il "fake" les "import" des sous-modules i.e. l'appelant fait ce qu'il veut, le code ré-organise tout çà.

    Les exemples concernant les lazy imports, justifie clairement une pénalité du temps d'exécution en cas de non respect de la PEP 8, il me semble, non?
    Il montre surtout comment faire pour ne pas être pénalisé.

    En fait quelle serait la bonne raison d'importer un module en dehors du début d'un fichier?
    L'exemple donné par PauseKawa qui est une sorte de pattern Strategy et les deux que je vous ai proposé sont de "bonnes" raisons.
    - W

  12. #12
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 889
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 889
    Points : 7 241
    Points
    7 241
    Par défaut
    Bon eh bien je vais relire tout ça tranquillement, merci

  13. #13
    Membre éclairé
    Avatar de clavier12AZQSWX
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Avril 2009
    Messages
    1 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 419
    Points : 874
    Points
    874
    Par défaut
    par exemple dans une cas de mon expérience.

    je devais créer un script qui réalise une opération suivant plusieurs process différent (un import via tel webservice, un autre via tel autre, encore un autre d'une marque différent...etc)

    bref, j'avais le choix entre faire ça :

    import ws_sony
    import ws_amstrad
    import ws_gloria

    (...)

    et ensuite dans le code, j'avais des choses comme ça

    if process_import==CS_sony: ...
    if process_import==CS_amstrad: ...
    if process_import==CS_gloria: ...

    du coup je me suis dit qu'il vallait mieux importer les modules dédiés en fonction des circonstances plutôt que tout plaquer en haut du fichier

    du coup au final, j'avais :
    if process_import==CS_sony:
    import import ws_sony ...
    if process_import==CS_amstrad: ...
    import ws_amstrad....
    if process_import==CS_gloria: ...
    import ws_gloria...


    Au départ je mettais toujours mes import en haut mais j'ai vu quelqu'un le faire (souvant des import datetime, ou strnig) les appeler à la volée et ça m'a semblait logique "pourquoi charger un module qu'on utilise pas partout"

    Et déjà en php, on (enfin moi) fait cela grâce à l'utilisation de include au lieu de require et mettre grace au chargement des modules à la volée de apache (plutôt que tout charger dans le .ini de php)

    bref, ce qui est bon en php et apache, est peut-être bon aussi en python ! En tout cas ça marche (ne produit pas d'erreur d'exécution, ni de compilation avec py2exe)

    La question est le coût (en terme de rapidité d'exécution, non pas en binaire compilé ça en ss'en fiche un peu)

  14. #14
    Membre chevronné

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Points : 1 752
    Points
    1 752
    Par défaut
    Pour ma part, je ferais un mini-script appelant un script suivant la fonctionnalité souhaitée sony, amstrad,...

    Ensuite en créant un script autonome pour sony, un autre amstrad,... on a aussi un moyen simple de débugguer les différents types d'appel.

  15. #15
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 297
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 297
    Points : 36 794
    Points
    36 794
    Par défaut
    Salut,

    A priori, la question n'est pas sur "import" mais plutôt sur des patterns de type Template et Strategy (comme illustré par PauseKawa) et leur déclinaison en Python (qui in fine se traduira par des "import")

    Imaginez que vous ayez à réaliser une gestion de verrouillage de fichiers soit multiOS. Vous allez définir une class disons "Locker" qui a deux méthodes acquire et release.
    La réalisation de ces opérations se traduira par des appels à des fonctions dont la réalisation sera spécifique à chaque os nommons les lock et unlock.
    Nous avons donc un module qui contient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import os
    class Locker:
        def acquire(self, timeout=None):
             ...
             os.lock(...)
             ...
        def release(self)
             ...
             os.unlock()
             ...
    Et le module os qui lorsqu'il est chargé définira les fonctions lock et unlock "adaptées" aux attentes de Locker en fonction de ce que l'OS veut bien
    faire. Ca peut être "compliqué" genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def w32_lockers():
        from msvcrt import locking, LK_NBLCK, LK_UNLCK, LK_LOCK
     
        def lock(fd, nbytes, blocking):
            if blocking:
                while True:
                    try:
                        locking(fd,  LK_LOCK, nbytes)
                    except IOError:
                        e = sys.exc_info()[1]
                        if e.errno not in LOCKING_ERRORS:
                            raise
                    else: return
            locking(fd,  LK_NBLCK, nbytes)
     
        def unlock(fd, nbytes):
            locking(fd,  LK_UNLCK, nbytes)
        return lock, unlock
    Le but étant d'avoir construit, dans le module os, en face des attributs 'lock' et 'unlock' attendu par "Lockers" la fonction qui va bien.

    L'avantage est qu'il n'y a plus de dépendance avec l'OS dans le module appelant (et donc plus de "if platform == ...")
    Et qu'on peut tester et construire les méthodes dépendantes de l'OS indépendamment.

    Dans votre cas la construction du spécifique semble fonction du choix de l'appelant, i.e. import du module "strategy" ne suffira pas, il faudra appeler une fonction ou construire l'instance d'une classe avec en paramètre "sony", "amstrad", ou "gloria".

    - W

Discussions similaires

  1. Quand est ce que le Rollback segment est écrit et par qui ?
    Par bach dans le forum Administration
    Réponses: 2
    Dernier message: 19/02/2009, 16h04
  2. quand est ce que on ajoute les classe associations
    Par jean sami dans le forum UML
    Réponses: 5
    Dernier message: 19/08/2008, 11h44
  3. Réponses: 2
    Dernier message: 18/12/2007, 22h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo