python开发注意事项

更新时间 🔔🕙 2024年3月29日

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.pyif __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"
转载请备注引用地址:编程记忆 » python开发注意事项