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 :

Intercepter une déclaration pour agir suivant ses arguments ?


Sujet :

Python

  1. #1
    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 Intercepter une déclaration pour agir suivant ses arguments ?
    Bonjour,

    Existe t'il une possibilité d'intercepter une déclaration (en l'occurrence import) pour agir suivant ses arguments ?

    Je m'explique. Si j'ai :

    import os
    import tutu

    J'aimerais savoir s'il est possible d'agir, comme un décorateur, lors d'une déclaration pour que suivant les arguments (ici os et tutu) soit on laisse faire (pour os) soit on exécute du code (savepath = os.getcwd()/os.chdir(dirdetutu)/exécution de l'import/os.chdir(savepath)).

    Je ne souhaite pas modifier/remplacer __import__ ni utiliser imp.

    Une idée ? Merci d'avance.

  2. #2
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Jette toujours un oeil du côté de sys.settrace

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (savepath = os.getcwd()/os.chdir(dirdetutu)/exécution de l'import/os.chdir(savepath)
    Si je comprends bien, tu veux importer un module qui n'est pas forcément dans le PythonPath. Tu peux sans doute ajouter un dossier à sys.path.

  3. #3
    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 Antoine_935,

    Malheureusement settrace ne permet pas l'interception du code avant son exécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import sys
     
    def traceur(frame, event, arg):
        if 'Tkinter' not in sys.modules: print 'nok'
        #print sys.modules
        #if event == 'call':
        return traceur
     
    sys.settrace(traceur)
    import Tkinter
    sys.settrace(None)
    Ou je m'y prend mal ? (fort possible)

    Citation Envoyé par Antoine_935 Voir le message
    Si je comprends bien, tu veux importer un module qui n'est pas forcément dans le PythonPath. Tu peux sans doute ajouter un dossier à sys.path.
    Presque : Le but est de charger des outils répartis dans plusieurs sous répertoires (connus ou résultat d'une recherche) et ce de la manière la moins 'destructive' possible.
    En fait cela fais plus ou moins suite à ce sujet et ma question (outre le fait de ne pas scater plus le sujet en question) n'est sans doute due qu'à l'effet d'un réchauffage de neurone. Mais bon, j'aime bien, je trouve cela sain

    Je garde toutefois de coté sys.settrace que je n'avais pas regarder de plus prés car signalé pour le debug. Merci.

  4. #4
    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 Antoine_935,

    J'avais pris ta réponse dans le sens de ma question mais l'idée n'est peut être pas mauvaise pour le sujet précédent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import sys
     
    def traceur(frame, event, arg):
        if ImportError: print 'nok'
        else: print 'ok'
        return traceur
     
    sys.settrace(traceur)
     
    import toto
    #import os
     
    sys.settrace(None)
    Il suffit de récupérer la commande avec linecache.getline et soit de faire une recherche avec os.walk ou glob pour rechercher les répertoires (utilisation du __all__ dans l'__init__) si l'on souhaite du dynamique, soit d'utiliser une liste/un dico déjà et d'appliquer cela.

    Je regarde cela dés que possible.

  5. #5
    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
    Bonsoir,

    Finalement pas très pratique en comparaison à un try.

    Une autre idée ? Moi je cale.

    Merci d'avance

  6. #6
    Membre éprouvé
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Malheureusement settrace ne permet pas l'interception du code avant son exécution
    Tiens, c'est pas idiot ça... j'y avais pas pensé

    J'ai essayé de trifouiller un peu le système d'imports en modifiant sys.modules. Eh bah c'est sans effet. Python semble garder une référence interne à sys.modules. Si on le remplace par un nouveau dictionnaire, il n'est plus mis à jour.

    Comportement normal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> import urllib
    >>> import sys
    >>> sys.modules["urllib"]
    <module 'urllib' from '/usr/lib/python2.6/urllib.pyc'>
    Comportement modifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> import urllib
    >>> sys.modules["urllib"]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'urllib'
    La seule solution me parait être de passer par le module imp et remplacer l'import standard. En tout cas, c'est certainement ce qu'il y a de plus propre.

  7. #7
    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
    Bonsoir Antoine_935,

    Dans un premier temps merci d'avoir jeter un œil sur la question.

    Depuis ta réponse j'ai regarder du coter des solutions de debug. Dans un cadre général je n'ai rien trouver qui permette de valider ou non du code.

    Pour ce qui est de import la réponse viens sans doute du code d'imp mais pour ce qui est du C...
    La solution la plus 'simple' semble être le module imp.
    Je dis 'simple' plutôt que 'propre' car à mon niveau je ne trouve pas qu'une modification d'un builtin soit une bonne idée

    Je laisse le sujet ouvert au cas ou.

    Encore merci de ton attention et bon code.

  8. #8
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Bonsoir,

    Après avoir parcouru cette discussion et la PEP 302, j'ai expérimenté un peu:
    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
    import sys, imp
     
    class MyImporter:
        def __init__(self):
            self.mod_info = {}
     
        def find_module(self, fullname, path=None):
            name = fullname.split('.')[-1]
            self.mod_info[fullname] = imp.find_module(name, path)
            return self
     
        def load_module(self, fullname):
            print "before importing", fullname
            mod = imp.load_module(fullname, *self.mod_info[fullname])
            print "after importing", fullname
            return mod
     
    sys.meta_path.append(MyImporter())
    Attention je ne suis pas sûr que ce soit correct, c'est assez délicat tout de même.
    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
    >>> import urllib
    before importing urllib
    before importing socket
    before importing _socket
    after importing _socket
    before importing _ssl
    after importing _ssl
    before importing errno
    after importing errno
    after importing socket
    before importing urlparse
    after importing urlparse
    before importing nturl2path
    after importing nturl2path
    after importing urllib
    >>> import xml.etree.ElementTree
    before importing xml
    after importing xml
    before importing xml.etree
    after importing xml.etree
    before importing xml.etree.ElementTree
    before importing xml.etree.ElementPath
    after importing xml.etree.ElementPath
    after importing xml.etree.ElementTree
    >>> reload(urllib)
    before importing urllib
    after importing urllib
    <module 'urllib' from 'C:\Python25\lib\urllib.pyc'>

  9. #9
    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 dividee,

    Voici une réponse qui vas redonner du PEP's au sujet.

    Dans le cadre de l'import ce que je souhaite éviter c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    The only way to customize the import mechanism is currently to
    override the built-in __import__ function.  However, overriding
    __import__ has many problems.  To begin with:
    
    - An __import__ replacement needs to *fully* reimplement the entire
      import mechanism, or call the original __import__ before or after
      the custom code.
    
    - It has very complex semantics and responsibilities
    Ton exemple sur les Meta hooks semble bien correspondre. Je retourne tester cela.

    Merci

  10. #10
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Oui c'est en lisant cela que je me suis dit qu'il valait mieux ne pas toucher à __import__. Mais cela reste assez délicat tout de même. Par exemple, quand find_module est appelé avec un nom qualifié (x.y.z), la PEP302 dit que les modules x et x.y sont déjà chargés, mais puis-je être sûr que l'argument path pointe là où il faut ? Si c'est le cas, pourquoi est-ce le nom qualifié qui est passé à la méthode plutôt que le nom relatif au path donné ?

    Est-ce qu'il ne faudrait pas protéger par un lock l'accès au dictionnaire (mod_info) pour être thread-safe ?

    Ce serait sans doute plus propre aussi de supprimer l'entrée du dictionnaire quand on n'en a plus besoin (après l'appel à imp.load_module) car elle contient une référence à un fichier ouvert, si je ne m'abuse. Mais serais-ce thread-safe ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Intercepter une erreur pour l'afficher proprement
    Par lebanner82 dans le forum Langage
    Réponses: 2
    Dernier message: 07/10/2013, 18h02
  2. Réponses: 0
    Dernier message: 20/05/2013, 18h31
  3. Intercepter une trame pour la modifier
    Par tom__63 dans le forum Réseau
    Réponses: 0
    Dernier message: 22/05/2009, 15h01
  4. Réponses: 38
    Dernier message: 22/03/2007, 16h15
  5. Une déclaration pour la survie du jeu vidéo en France
    Par Freakazoid dans le forum DirectX
    Réponses: 1
    Dernier message: 30/10/2002, 14h31

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