【问题标题】:python not able to share variable across files [duplicate]python无法跨文件共享变量[重复]
【发布时间】:2021-11-07 03:55:45
【问题描述】:

所以我读到跨文件共享全局变量的方法是创建一个包含全局变量的模块并将其导入需要访问全局变量的所有 python 文件中。但是它似乎对我来说没有按预期工作(Python 3.6+)

简单的目录结构:

run.py
mypack/
   -- globals.py
   -- stuff.py
   -- __init__.py

我在 globals.py 中有一个全局变量,我需要在主文件 (run.py) 中对其进行修改,最后在退出程序时打印出来。它似乎不起作用:

__init__.py:

from .stuff import *

globals.py:

test = 'FAIL'

stuff.py:

import atexit
from .globals import test

def cya():
    print ("EXIT: test = " + test)

atexit.register(cya)

def hi():
    print('HI')

运行.py:

import mypack
import mypack.globals as globals

mypack.hi()
globals.test = 'PASS'

print ("MAIN: test = " + globals.test)

脚本执行的输出:

HI
MAIN: test = PASS
EXIT: test = FAIL

显然,退出例程 (cya) 没有显示在 run.py 中修改的全局值的正确值。不知道我做错了什么。

【问题讨论】:

  • 附注 - 不要使用 globals 作为模块名称/别名。这是built-in functiom
  • @buran 谢谢 - 所以我将 globals 更改为 universal 以供我使用。无论如何,它不会改变问题。
  • 如果您多次导入 globls,变量会在每次导入时重新初始化。您应该创建单例对象。
  • @PeterTrcka 很棒 - 这就是问题所在
  • @PeterTrcka 绝对不正确

标签: python global-variables


【解决方案1】:

【讨论】:

  • 这就是我使用模块存储全局变量的想法。但是在实施时,它并没有按预期工作。
  • 试试stuff.test = "whatever"?
  • mypack.stuff.test = 'whatever' 有效,但它违背了目的。目的不是修改模块局部变量。它是只修改全局模块中的变量并始终反映。
  • 我想我不明白你的问题吗?您似乎正在尝试修改不同文件中的变量数据。
  • 我的真实用例是跨模块传递 logger 和 log_count 变量(不是字符串,而是其他对象)。但我只是在这里提出了一个更简单的问题来解释这个问题。我可能会创建几个模块。每个人都需要访问全局并可能对其进行修改。让每个模块从每个其他模块访问局部变量是不可行的。我想导入一组全局变量,并确保对它们的修改立即反映在其他每个模块中。
【解决方案2】:

感谢@PeterTrcka 指出问题。还要感谢@buran 指出全局变量是模块的一个坏名字,因为它的内置功能。这是可行的解决方案:

目录结构:

run.py
mypack/
   -- universal.py
   -- stuff.py
   -- __init__.py

__init__.py:

from .stuff import *

universal.py:

class GlobalVars:
  test = 'FAIL'

stuff.py:

import atexit
from .universal import GlobalVars

def cya():
    print ("EXIT: test = " + GlobalVars.test)

atexit.register(cya)

def hi():
    print('HI')

运行.py:

import mypack
from mypack.universal import GlobalVars

mypack.hi()
GlobalVars.test = 'PASS'

print ("MAIN: test = " + GlobalVars.test)

脚本执行的输出:

HI
MAIN: test = PASS
EXIT: test = PASS

【讨论】:

  • 这不是实际问题,模块不会在每次导入时重新初始化。
  • @juanpa.arrivillaga 那么上述解决方案如何工作,但原始问题失败了?
  • 问题是您正在像这样导入:from .globals import test。这会在当前模块中创建一个 new 变量。使用import globals,然后在cya 中使用globals.test
  • @juanpa.arrivillaga 感谢您提供正确的解决方案。我没有意识到这会创建一个新的局部变量。所以我猜真的没有捷径可以访问全局变量。
  • 它不创建局部变量,它创建一个全局变量。全局变量实际上只是 Python 中的“模块级别”。这是好事
【解决方案3】:

问题是:在每次导入时,所有变量都将重新初始化它们的值。使用单例对象:

universal.py

import logging


class GlobVars:

    _instances = {}
    
    def __new__(cls, logger, counter_start=0):
        if cls not in cls._instances:
            print("Creating Instance")
            cls._instances[cls] = super(GlobVars, cls).__new__(cls)
        return cls._instances[cls]

    def __init__(self, logger, counter_start=0):
        self.logger = logger
        self.counter = counter_start

glob_vars = GlobVars(logger=logging.getLogger("basic_logger"))

run.py

from universal import glob_vars

glob_vars.logger.info("One logger rulles them all")

【讨论】:

  • 这是完全错误
  • @juanpa.arrivillaga 你能解释为什么这是错误的。将它添加到对我有用的课程中。
  • 你能说得更具体点吗?这种类型的 cmets 没有帮助。
  • 您声称模块已重新初始化。完全错误。并且很容易验证为错误。
  • @PeterTrcka 完全错误。他们绝对不会重新初始化。是的,模块一旦被导入就会被缓存。 OP 的问题是他们使用了from .globals import test,这会在执行此操作的模块中创建一个新的全局变量。对global.test 的赋值不会影响那个变量。查看链接的副本
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 2016-07-07
  • 1970-01-01
  • 2016-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多