1、没有使用global进行标记
python开发中有时候会发现全局变量修改无效,在当前py文件中是修改成功的,但是跳转到其他py文件中无效。此时要注意,修改全局变量的时候,需要加入一行代码global global_var
,才表示修改的是全局变量。
def set_global_var(value: int): global global_var global_var = value
2、main方法中使用了全局变量,后续其他py文件中修改无效
如果main方法就在a.py的文件中,在import a.py之前,在main方法中使用了a.py的全局变量C,后续在b.py中修改了a.py的全局变量C的修改不会生效。
当你在a.py
中定义了全局变量,并且在同一个文件(a.py
)的if __name__ == "__main__":
块中使用这个全局变量,然后在另一个文件(比如b.py
)中修改这个全局变量,你的期望是在a.py
中对这个全局变量的修改能够反映出来。但实际情况会有所不同,这里我们详细解释一下原因和可能的解决方案。
场景概述
- a.py:定义了全局变量
C
,并且在if __name__ == "__main__":
块中使用了C
。 - b.py:导入
a.py
并修改全局变量C
。
为什么修改不会生效
当你运行a.py
时,__name__
变量被设置为"__main__"
,这意味着if __name__ == "__main__":
块中的代码会被执行。如果在这个时候b.py
尝试导入a.py
,由于Python模块的导入机制设计为只导入一次以避免重复导入带来的性能损失,因此在b.py
中对a.py
的全局变量C
的修改是在一个不同的上下文中进行的,这个修改只会影响后续的导入和使用,而不会反映到已经执行的if __name__ == "__main__":
块中的使用。
示例说明
# a.py的代码 C = 10 def print_C(): print("a.py:", C) if __name__ == "__main__": print_C() # 第一次打印C的值 import b print_C() # 第一次打印C的值
import a a.C = 20 # 试图修改a.py中的C a.print_C() # 检查C的值是否已经被修改
当你直接运行a.py
,它会首先打印C
的原始值(例如:a.py: 10
),然后尽管b.py
修改了C
的值并且在b.py
的上下文中这个修改是有效的(a.print_C()
会打印出修改后的值),但是这个修改对a.py
中if __name__ == "__main__":
块的执行没有影响,因为那部分代码在b.py
修改C
之前就已经执行了。
执行结果:
a.py: 10 a.py: 20 a.py: 10 #main中打印时,a.C的值没有被修改过来
解决方案
这个问题的根源在于Python的模块导入机制和执行流程,理解这一点有助于更好地组织和设计你的代码结构。
- 如果你想要在
a.py
运行结束后看到修改,你需要确保在修改全局变量C
之后再进行依赖于C
的操作。这可能意味着需要重新组织代码结构,或者通过其他机制(例如定义一个函数来专门修改和处理C
,然后在适当的时候调用这个函数)。 - 如果目的是实现某种类型的配置或状态管理,考虑使用配置文件、环境变量或者专门的状态管理模块,而不是依赖于修改模块级别的全局变量。
- (👍推荐)把
main
方法单独放到一个文件main.py
中,这样main.py
就只能明确写import a
,此时后续的a.py模块都在同一个上下文环境,执行a.C
的修改就统一了。
# main.py import a if __name__ == "__main__": a.print_C() # 第一次打印C的值 import b a.print_C()
3、使用poetry的时候,增加自定义pypi源
可以在pyproject.toml中,在[build-system
]的前面,加入下面的代码(primary
表示是主源,supplemental
表示是补充源)
[[tool.poetry.source]] name = "tencent" url = "https://mirrors.cloud.tencent.com/pypi/simple/" priority = "primary" [[tool.poetry.source]] name = "aliyun" url = "http://mirrors.aliyun.com/pypi/simple/" priority = "supplemental" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api"