Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

pb de variable avec modularisation du code...

5 réponses
Avatar
Yann.K
--nextPart2109861.h2NsfPMHsU
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8Bit

Bonjour à toous.

Je tente péniblement de me mettre à python. ;-)
Pour me faire la main, j'essaye de passer une appli écrite en bash en python
avec interface graphique.
Pour bien faire, je tente de modulariser le code afin de mettre, par
exemple, mes fonctions communes dans un script, telle ou telle fenetre
graphique dans un autre etc...

Cela fonctionne à peu prét, sauf quand dans certains cas liés à des
problèmes de transmissions de variables semble-t-il (meme si je déclare la
variable comme globale dans la fonction).

J'aimerai bien comprendre comment fonctionne python dans l'importation des
modules.
Pourquois si j'importe ("import" ou "from") un module dans mon script de
départ, suis-je obligé de le réimporter dans un script lié qui l'utilise,
Par exemple, dans les fichiers joints, je suis obligé d'importer le module
tkMessageBox dans "script1b.py", même si je l'ai déjà importé dans
"script1a.py".

Pour finir, pourquois, lorsque je mets tout dans le même script ("script
1.py") cela fonctionne, et pourquois cela ne fonctionne pas quand je
modularise ce code sur les deux scripts "script1a.py" et "script1b.py" (les
commandes sont exactment les mêmes)?...


Merci de votre aide et de votre patience.

--
Yann.K
--nextPart2109861.h2NsfPMHsU
Content-Type: text/plain; name="script1a.py"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="script1a.py"

# -*- coding: utf-8 -*-
#
# script1a.py
#
#!/usr/bin/env python

from Tkinter import *
import tkMessageBox
import script1b


root = Tk()
root.protocol("WM_DELETE_WINDOW", script1b.callback)
root.mainloop()

--nextPart2109861.h2NsfPMHsU
Content-Type: text/plain; name="script1b.py"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="script1b.py"

# -*- coding: utf-8 -*-
#
# script1b.py
#
#!/usr/bin/env python

import tkMessageBox

def callback(event=''):
"Boite de message quitter"
if tkMessageBox.askokcancel(
"Quitter",
"Souhaiter vous réellement quitter?"
):
root.destroy()

--nextPart2109861.h2NsfPMHsU
Content-Type: text/plain; name="script1.py"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="script1.py"

# -*- coding: utf-8 -*-
#
# script.py
#
#!/usr/bin/env python

from Tkinter import *
import tkMessageBox

def callback(event=''):
"Boite de message quitter"
if tkMessageBox.askokcancel(
"Quitter",
"Souhaiter vous réeellement quitter?"
):
root.destroy()


root = Tk()
root.protocol("WM_DELETE_WINDOW", callback)
root.mainloop()

--nextPart2109861.h2NsfPMHsU--

5 réponses

Avatar
Yann.K
huron benoit wrote:
Si ce que je dis vous apparaît confus, ...
Non, après une lecture attentive et soutenue, j'ai fini par tout comprendre!

Je vous remercie d'ailleurs pour cette réponse qui a du vous prendre du
temps!

- lire le tutorial de Guido (p37-38)
en cours...


- lire Learning Python (chapitre module, très fouillé)
En projet ;-)


- demandez des précisions aux membres du forum.
Ce que je fais en ce moment!


Mais pour ne revenir à nos moutons (si j'ose dire), comment donc, faire
passer la valeur de la variable root (definie dans le module importateur) à
la fonction contenu dans le module importé?...
J'ai bien tenté de la transmettre par l'intermédiaire de l'appel à la dite
fonction, mais la reception par la fonction se passe mal...

Merci de votre aide.

--
Yann.K

Avatar
huron benoit
Yann.K wrote:

J'aimerai bien comprendre comment fonctionne python dans l'importation des
modules.
Pourquois si j'importe ("import" ou "from") un module dans mon script de
départ, suis-je obligé de le réimporter dans un script lié qui l'utilise,
Par exemple, dans les fichiers joints, je suis obligé d'importer le module
tkMessageBox dans "script1b.py", même si je l'ai déjà importé dans
"script1a.py".

Pour finir, pourquois, lorsque je mets tout dans le même script ("script
1.py") cela fonctionne, et pourquois cela ne fonctionne pas quand je
modularise ce code sur les deux scripts "script1a.py" et "script1b.py" (les
commandes sont exactment les mêmes)?...




Voici le mécanisme général d'importation (P.Hansen) :

Importer un module (i.e import modulexxx) signifie qu'un nouvel objet
module est crée, une référence à cet objet est inséré dans le
dictionnaire sys.modules, toutes les instructions du module sont
exécutées, puis dans l'espace de noms du module importateur (celui qui a
l'instruction import), est ajouté un nom "modulexxx" qui refère au
nouvel objet module juste crée.
Si vous utilisez la forme "from module import *", tout cela se passe
aussi mais au lieu d'un seul nom dans le module importateur vous avez
-tous- les noms définis au niveau supérieur du module importé.


Voici pour votre programme en particulier :

Le corps d'un module (la suite de statements qu'il contient) est exécuté
dès que le module est importé. Dans votre cas python exécute donc le
corps de script1b.py. C'est-à-dire les deux instructions qu'il contient:

1- import tkMessageBox
(pas de problèmes ici)

2- def callback(event=''):
"Boite de message quitter"
if tkMessageBox.askokcancel(
"Quitter",
"Souhaiter vous réellement quitter?"
):
root.destroy()


Python ne rencontre pas non plus de problème ici. Une instruction def a
pour effet de créer un objet fonction (et de le munir de quelques
attributs) et de le lier (dans la portée en cours, ici l'espace de nom
de l'objet module) au nom fourni (ici
callback). Mais les instructions -contenues- dans l'objet ainsi crée (et
lié) ne sont executées que lorsque la fonction est appelée (par son nom
en général). Il faut donc distinguer l'instruction def (qui lie)
exécutée immédiatement et les instructions contenue dans le corps de la
fonction.
Donc ayant exécuté son instruction def,et par la même ayant fini
d'exécuter tout le module script1b, Python continue l'execution de script1a.
Il y execute :
root.protocol("WM_DELETE_WINDOW", script1b.callback)
C'est-à-dire qu'il appelle l'objet fonction (de nom callback) contenu
dans le module script1b. Cela a pour effet qu'il va essayer d'executer
les instruction contenues dans cette objet fonction :

if tkMessageBox.askokcancel(
"Quitter",
"Souhaiter vous réellement quitter?"
):
root.destroy() <- problème !


Face à l'instruction root.destroy() Python cherche le nom root. D'abord
dans l'espace de nom local à la fonction. Il ne le trouve pas. Il
cherche alors au niveau supérieur. C'est ici que ça devient drôle.

Chaque objet module à son espace de noms propre qui contient ses
attributs, i.e les noms définis au niveau supérieur (global) du fichier
module.py. Or, cet espace de nom est utilisé comme espace de noms global
par toutes les fonctions définies dans le module.
C'est-à-dire que, n'ayant pas trouvé le nom root dans l'espace de noms
local à la fonction callback, Python cherche dans ce qui pour la
fonction est l'espace global, mais qui pour nous, et pour le script
importateur, est l'espace de nom de l'objet module nommée scriptb1.
Evidemment Python ne trouve pas non plus le nom root. Et comme il ne
connaît pas d'autres niveaux au dessus du global, il s'arrête avec un
NameError (c'est-ça ? Si je dis n'importe quoi, il faut me le dire).


Pour finir, pourquois, lorsque je mets tout dans le même script ("script
1.py") cela fonctionne, et pourquois cela ne fonctionne pas quand je
modularise ce code sur les deux scripts "script1a.py" et
"script1b.py" (les
commandes sont exactment les mêmes)?...


Lorsque vous mettez tout dans le même script, vous résolvez les
problèmes d'importation (en fait vous les supprimez). Python peut alors
exécuter root.destroy car il ne cherche plus root dans les attributs
d'un objet module (que vous n'avez pas crée) mais dans l'espace global
de script1.py. Et il le trouve !

Si ce que je dis vous apparaît confus, vous pouvez :

- lire le tutorial de Guido (p37-38)
- lire Learning Python (chapitre module, très fouillé)
- demandez des précisions aux membres du forum.

Benoît.

Avatar
huron benoit
Yann.K wrote:


Mais pour ne revenir à nos moutons (si j'ose dire), comment donc, faire
passer la valeur de la variable root (definie dans le module importateur) à
la fonction contenu dans le module importé?...
J'ai bien tenté de la transmettre par l'intermédiaire de l'appel à la dite
fonction, mais la reception par la fonction se passe mal...



Il suffit de faire passer l'objet contenue dans votre variable root dans
une variable (de même nom) de l'espace de noms de votre module (puisque
c'est dans cet espace que votre fonction va chercher root ).

Cela donne :

# -*- coding: utf-8 -*-
#
# script1a.py
#
#!/usr/bin/env python

from Tkinter import *
import tkMessageBox
import script1b


root = Tk()
script1b.root = root # ligne rajoutée par moi
root.protocol("WM_DELETE_WINDOW", script1b.callback)
root.mainloop()

Cela devrait marcher.
Benoît.

Avatar
Yann.K
huron benoit wrote:
script1b.root = root # ligne rajoutée par moi
root.protocol("WM_DELETE_WINDOW", script1b.callback)
Naturellement...


Cela devrait marcher.
Et oui, ça marche.

Il n'empéche que je trouve cela un peu lourd et inestetique...
Il faut donc bien reflechir avant de modulariser.

Merci pour vos explication qui m'ont permis d'y voir beaucoup plus clair.

Du coup, j'ai craqué cette après-midi et je veins de commander "Python en
concentre : Manuel de reference de A.Martelly (la traduction de "Python in
a nutshell" si je ne m'abuse)...
Violà quelque soirées d'occupées pour l'avenir :-)

Cordialement,

--
Yann.K

Avatar
Bruno Desthuilliers
Yann.K wrote:
Bonjour à toous.

Je tente péniblement de me mettre à python. ;-)
"Péniblement" ?


Pour me faire la main, j'essaye de passer une appli écrite en bash en python
avec interface graphique.
Pour bien faire, je tente de modulariser le code afin de mettre, par
exemple, mes fonctions communes dans un script, telle ou telle fenetre
graphique dans un autre etc...

Cela fonctionne à peu prét, sauf quand dans certains cas liés à des
problèmes de transmissions de variables semble-t-il (meme si je déclare la
variable comme globale dans la fonction).
Ce qui est a éviter...


J'aimerai bien comprendre comment fonctionne python dans l'importation des
modules.
J'aurais dit "comment fonctionne l'importation des modules en Python" !-)

Tout ça est dans la doc :
"""
Import statements are executed in two steps: (1) find a module, and
initialize it if necessary; (2) define a name or names in the local
namespace (of the scope where the import statement occurs).
"""

Pourquois si j'importe ("import" ou "from") un module dans mon script de
départ, suis-je obligé de le réimporter dans un script lié qui l'utilise,


cf ci-dessus. Les symboles importés sont définis dans l'espace de
nommage *local*.

8<------------------------
#toto.py

import sys

def testToto():
print "test toto"


8<------------------------
#titi.py

import toto


Python 2.3.3 (#1, Apr 22 2004, 12:11:30)
[GCC 3.2.2 (Mandrake Linux 9.1 3.2.2-3mdk)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import titi
dir()
['__builtins__', '__doc__', '__name__', 'titi']



dir(titi)
['__builtins__', '__doc__', '__file__', '__name__', 'toto']



titi.toto.testToto()
test toto



titi.toto.sys
<module 'sys' (built-in)>










Par exemple, dans les fichiers joints, je suis obligé d'importer le module
tkMessageBox dans "script1b.py", même si je l'ai déjà importé dans
"script1a.py".


Comprend bien que l'import de module en Python est très différent de
l'inclusion de fichier en C ou en PHP. Le module script1b.py n'est pas
supposé savoir a priori ce que le module script1a.py a importé, ni même
savoir que script1a.py existe.

Pour finir, pourquois, lorsque je mets tout dans le même script ("script
1.py") cela fonctionne, et pourquois cela ne fonctionne pas quand je
modularise ce code sur les deux scripts "script1a.py" et "script1b.py" (les
commandes sont exactment les mêmes)?...


"fonctionne" et "ne fonctionnent pas" ne sont pas des informations
utiles quand on décrit un problème de programmation !-)

Poste un exemple de code minimum reproduisant ton problème, avec
description précise de ce que tu attend comme résultat et du résultat
obtenu. Là, on aura une base pour discuter.


Merci de votre aide et de votre patience.

Bienvenu.