333 votes

Utilisation de variables globales entre les fichiers ?

Je suis un peu confus sur le fonctionnement des variables globales. J'ai un grand projet, avec environ 50 fichiers, et j'ai besoin de définir des variables globales pour tous ces fichiers.

Ce que j'ai fait était de les définir dans le fichier main.py de mon projet, comme suit :

# ../monprojet/main.py

# Définir global myList
global myList
myList = []

# Imports
import subfile

# Faire quelque chose
subfile.stuff()
print(myList[0])

J'essaie d'utiliser myList dans subfile.py, comme suit

# ../monprojet/subfile.py

# Enregistrer "hey" dans myList
def stuff():
    globals()["myList"].append("hey")

Une autre façon que j'ai essayée, mais qui n'a pas fonctionné non plus

# ../monprojet/main.py

# Import globfile    
import globfile

# Enregistrer myList dans globfile
globfile.myList = []

# Import subfile
import subfile

# Faire quelque chose
subfile.stuff()
print(globfile.myList[0])

Et à l'intérieur de subfile.py j'avais ceci :

# ../monprojet/subfile.py

# Import globfile
import globfile

# Enregistrer "hey" dans myList
def stuff():
    globfile.myList.append("hey")

Mais encore une fois, ça n'a pas fonctionné. Comment devrais-je implémenter cela ? Je comprends que cela ne peut pas fonctionner comme ça, lorsque les deux fichiers ne se connaissent pas vraiment (enfin subfile ne connaît pas main), mais je ne vois pas comment le faire, sans utiliser l'écriture io ou pickle, ce que je ne veux pas faire.

4voto

MikeHunter Points 1388

Votre deuxième tentative fonctionnera parfaitement et est en fait une très bonne manière de gérer les noms de variables que vous souhaitez avoir disponibles globalement. Mais vous avez une erreur de nom dans la dernière ligne. Voici comment ça devrait être :

# ../myproject/main.py

# Importez globfile
import globfile

# Sauvegardez myList dans globfile
globfile.myList = []

# Importez subfile
import subfile

# Faites quelque chose
subfile.stuff()
print(globfile.myList[0])

Vous voyez la dernière ligne ? myList est un attribut de globfile, pas de subfile. Cela fonctionnera comme vous le souhaitez.

Mike

3voto

qel Points 747

Les cauchemars de l'espace de noms surviennent lorsque vous utilisez from config import mySharedThing. Ce point ne peut pas être suffisamment souligné.

Il est ok d'utiliser from ailleurs.

Vous pouvez même avoir un module config totalement vide.

# my_config.py
pass

# my_other_module.py
import my_config

def doSomething():
    print(my_config.mySharedThing.message)

# main.py
from dataclasses import dataclass
from my_other_module import doSomething
import my_config

@dataclass
class Thing:
    message: str

my_config.mySharedThing = Thing('Hey everyone!')
doSomething()

résultat:

$ python3 main.py
Hey everyone!

Mais utiliser des objets que vous avez importés avec from vous mènera à une voie de frustration.

# my_other_module.py
from my_config import mySharedThing

def doSomething():
    print(mySharedThing.message)

résultat:

$ python3 main.py
ImportError: impossibile d'importer le nom 'mySharedThing' depuis 'my_config' (my_config.py)

Et peut-être que vous allez essayer de le résoudre comme ceci:

# my_config.py
mySharedThing = None

résultat:

$ python3 main.py
AttributeError: l'objet de type 'NoneType' n'a pas l'attribut 'message'

Et ensuite peut-être que vous trouverez cette page et essayerez de résoudre le problème en ajoutant une méthode init().

Mais le problème entier est le from.

2voto

DevelJoe Points 381

Je suis tombé sur ce post et j'ai pensé à partager ma solution, au cas où quelqu'un se retrouverait dans la même situation que moi, avec de nombreux fichiers dans le programme développé, et où vous n'avez pas le temps de réfléchir à toute la séquence d'importation de vos modules (si vous n'y avez pas pensé correctement dès le départ, comme moi).

Dans de tels cas, dans le script où vous initialisez vos globales, il suffit de coder une classe qui ressemble à ceci :

class My_Globals:
  def __init__(self):
    self.global1 = "valeur_initiale_1"
    self.global2 = "valeur_initiale_2"
    ...

et ensuite utilisez, au lieu de la ligne dans votre script où vous avez initié vos globales, au lieu de

global1 = "valeur_initiale_1"

utilisez

globals = My_Globals()

J'ai ensuite pu récupérer / modifier les valeurs de l'une de ces globales via

globals.global_voulue

dans n'importe quel script, et ces changements étaient automatiquement appliqués à tous les autres scripts les utilisant. Tout fonctionnait maintenant, en utilisant les mêmes instructions d'importation qui échouaient auparavant, en raison des problèmes mentionnés dans ce post / cette discussion. Je me suis simplement dit que les propriétés des objets globaux pouvaient changer de manière dynamique sans avoir besoin de considérer / changer toute logique d'importation, par rapport à l'importation simple de variables globales, et c'était certainement l'approche la plus rapide et la plus facile (pour un accès ultérieur) pour résoudre ce genre de problème pour moi.

2voto

WinEunuuchs2Unix Points 366

Basé sur les réponses ci-dessus et les liens à l'intérieur, j'ai créé un nouveau module appelé global_variables.py:

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

# ==============================================================================
#
#       global_variables.py - Variables globales partagées par tous les modules.
#
# ==============================================================================

USER = None                 # L'ID de l'utilisateur, le nom, le GUID varient en fonction de la plateforme

def init():
    """ Cela ne doit être appelé qu'une seule fois par le module principal
        Les modules enfants hériteront des valeurs. Par exemple s'ils contiennent

            import global_variables as g

        Plus tard, ils pourront faire référence à 'g.USER' pour obtenir l'identifiant de l'utilisateur.
    """
    global USER

    import getpass
    USER = getpass.getuser()

# Fin de global_variables.py

Ensuite, dans mon module principal j'utilise ceci:

import global_variables as g
g.init()

Dans un autre module enfant importé, je peux utiliser ceci:

import global_variables as g
# des centaines de lignes plus tard....
print(g.USER)

J'ai seulement passé quelques minutes à tester dans deux programmes python multi-modules différents, mais jusqu'à présent, tout fonctionne parfaitement.

0voto

Clóvis Fritzen Points 141

J'ai vu une fois quelque part sur Internet (désolé, je ne me souviens pas où) la méthode suivante (que j'utilise depuis lors) :

  1. Créez un fichier appelé (par exemple) variables.py où vous déclarez tous vos globaux, ex :

    variable1=0.0 variable2= "mon texte"

  2. Appelez ces variables où vous le souhaitez (dans d'autres fichiers par exemple) :

    variables.variable1= 1 (ici en lui attribuant 1)

Édition : j'ai trouvé un exemple : https://www.edureka.co/community/52900/how-do-i-share-global-variables-across-modules-python

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X