如何区分并拆分os.environ为默认环境变量与自定义变量?
问题
能否将os.environ拆分为默认环境变量与自定义添加的变量?比如用集合语法计算自定义变量的键:
custom_addon_env_var_keys = set(os.environ.keys()) - set(os.environ.default.keys()) # 是否存在类似os.environ.default的属性?
有没有类似os.environ.default的方式,在程序启动后获取纯净的环境变量(排除程序启动后添加的所有自定义键)?
我查看了os模块的源码,environ由_createenviron函数初始化,但该函数在environ初始化后就被删除了,无法重新初始化一个environ_2来实现需求,复制整个初始化函数又显得笨拙。
下面的代码展示了期望的行为,但因为我要把它用于跨文件变量,所以无法在启动时保存原始副本:
import os # 因用于跨文件变量,无法在启动时保存原始副本 ORIGINAL_ENV_COPY = os.environ.copy() os.environ["MY_CUSTOM_ENV_KEY"] = "HelloWorld" # ORIGINAL_ENV_COPY应是获取os.environ原始版本的方式 custom_addon_env_var_keys = set(os.environ.keys()) - set(ORIGINAL_ENV_COPY.keys()) print(custom_addon_env_var_keys) # 输出: {"MY_CUSTOM_ENV_KEY"}
补充说明
我有一个名为environment.py的文件用于初始化常量,它会和main.py一起打包成二进制可执行文件,部分代码如下:
import os import random import sys os.environ["TIMEZONE"] = "Asia/Taipei" os.environ["PROJECT_NAME"] = "Project name" os.environ["APP_USER_MODEL_ID"] = f"{os.environ['PROJECT_NAME']}.App.User.Model.Id" os.environ["SERVER_URL"] = f"https://www.my.server.io/projects/{os.environ['PROJECT_NAME']}" os.environ["STORAGE_URL"] = f"https://www.my.server.io/projects/{os.environ['PROJECT_NAME']}/Storage" os.environ["MODULES_URL"] = f"https://www.my.server.io/projects/{os.environ['PROJECT_NAME']}/Modules" os.environ["USER_AGENT"] = random.choice([ "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/61.0", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15" ]) if getattr(sys, "frozen", False): sys.argv = [arg for arg in sys.argv if not arg.startswith("-")] os.environ["EXECUTABLE_ROOT"] = os.path.dirname(sys.executable) else: os.environ["EXECUTABLE_ROOT"] = os.path.dirname(os.path.abspath(sys.modules["__main__"].__file__))
为何要将变量和常量存入os.environ?
environment.py会和main.py一起打包成二进制可执行文件,其他模块不知道该文件的存在(只剩main.exe);- 部分变量如
USER_AGENT、EXECUTABLE_ROOT代码量较大,存入可避免重复代码。
为何需要获取自定义环境变量键?
因为我将变量存入其中,收到崩溃报告时需调试是否由这些变量导致问题。例如USER_AGENT,若其中某个不可用,我需要知道是哪个引发错误并将其移除,而非逐个测试。且默认环境变量键众多,全部发送会杂乱,我只需自己添加的键。
解决方案(感谢@zondo)
使用setattr将原始os.environ保存到os模块下,并通过if语句避免重新导入时覆盖原始保存:
import os # 首次运行时不存在default_environ属性 if not hasattr(os, "default_environ"): setattr(os, "default_environ", os.environ.copy()) # ... 其他变量初始化代码
内容的提问来源于stack exchange,提问作者Head Cracked
相关产品推荐
相关产品推荐

