PyInstaller打包.pyw文件时tqdm.contrib.telegram的trange失效报错
问题原因
.pyw格式脚本运行时不会创建控制台窗口,导致sys.stdout和sys.stderr被设为None。而tqdm.contrib.telegram的内部实现依赖标准输出流,当尝试调用write方法时,就会触发'NoneType' object has no attribute 'write'错误。
解决方案
方案1:重定向标准输出/错误流
在代码开头导入sys和io,并在main函数初始化阶段,手动将标准输出和错误流重定向到内存对象或日志文件:
import sys import io def main() -> None: # 处理.pyw环境下的标准流缺失问题 if sys.stdout is None: # 可替换为日志文件路径(如'./app.log')实现持久化日志记录 sys.stdout = io.StringIO() if sys.stderr is None: sys.stderr = io.StringIO() # 原有业务代码保持不变 load_dotenv() global config,telegram_token config = { 'telegramToken': os.environ['TELEGRAM_BOT_TOKEN'] } telegram_token = config['telegramToken'] telegram_token = mycrypto.crypto(telegram_token,'decrypt') # ...后续代码无需修改
方案2:指定trange的输出流参数
调用trange时,手动传入一个有效的IO对象作为file参数,避免依赖默认的标准输出:
from io import StringIO async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: chatid = update.message.chat_id my_df = 100 # 创建空的StringIO对象作为替代输出流 dummy_output = StringIO() for i in trange(my_df, token=telegram_token, chat_id=chatid, desc='process', miniters=5, maxinterval=200, file=dummy_output): sleep(0.5)
方案3:PyInstaller强制保留控制台(备选)
若可接受后台存在控制台窗口,打包时添加--console参数强制创建控制台:
pyinstaller --onefile --console your_script.pyw
此方案会打破静默运行需求,仅适用于调试或特殊场景。
验证步骤
修改代码后,重新用PyInstaller打包为.pyw格式的exe文件,发送/start命令测试进度条是否正常推送,且无报错。
内容的提问来源于stack exchange,提问作者Nguyen Nam
相关产品推荐
相关产品推荐

