今天我再次遇到这个玄学的事情:当我直接运行程序,运行失败;当我调试运行程序,运行成功。
我通过在程序中插入打印语句来观察程序的状态。好一番功夫才发现,直接运行程序时加载的配置信息是旧的,而调试运行时程序加载的配置信息是新的(所以我才一直发现不了)。
程序中会用到的敏感信息,如用户名和密码被我保存在项目根目录下的.env
文件中,程序启动时从文件加载信息到settings
对象,用到的时候取settings
对象的指定成员变量。代码如下:
from typing import Optional
from pydantic import PostgresDsn, HttpUrl, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
# Bitcoin Node Settings
bitcoin_rpc_url: HttpUrl = Field(default="http://localhost:8332")
bitcoin_rpc_user: str
bitcoin_rpc_password: str
# Database Settings
database_url: PostgresDsn
# Analysis Settings
min_whale_balance: float = Field(default=1000.0)
block_batch_size: int = Field(default=100)
max_workers: int = Field(default=4)
# Logging Settings
log_level: str = Field(default="INFO")
metrics_enabled: bool = Field(default=True)
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding='utf-8',
case_sensitive=False,
extra='ignore' # 添加这行来忽略额外的输入
)
if __name__ == '__main__':
s = Settings()
print(s.bitcoin_rpc_user)
print(s.bitcoin_rpc_password)
我修改了.env
中保存的信息,但是,这些信息已经被缓存到了环境变量中,Pydantic 加载配置的优先级是: 系统环境变量 > .env 文件,所以在我直接运行程序时加载的就是旧的信息。
直接读取环境变量信息,可以发现是旧信息:
if __name__ == '__main__':
import os
print(os.getcwd())
print(os.environ.get('BITCOIN_RPC_USER'))
而调试程序时,程序在一个新的 shell 环境中运行,会重新加载.env
中的信息,所以程序运行正常。
解决办法:开一个新的 shell 来运行程序。