引入Cryptography Fernet导致Windows服务无法启动的解决求助
问题描述
在Windows服务脚本中启用from cryptography.fernet import Fernet导入后,执行服务停止命令会报错;打包依赖Fernet的独立自定义模块(该模块在.toml中声明依赖Fernet)后,服务完全无法运行。注释掉Fernet导入时服务运行正常,单独卸载重装Fernet临时有效,但打包后问题复现。
可复现代码(需修改日志路径)
my_service.py
import logging logging.basicConfig(filename=r'C:\path\to\where\windows\service\is\service_log.txt', level=logging.DEBUG) import os import sys import time import multiprocessing from multiprocessing.connection import Listener import json import winreg import win32crypt # 让boto3在多线程下正常工作所需 from concurrent.futures import ThreadPoolExecutor # 服务相关依赖 import win32serviceutil import win32service import win32event import servicemanager # from cryptography.fernet import Fernet # 取消注释后出现问题 class OnePrintService(win32serviceutil.ServiceFramework): _svc_name_ = "TestService" _svc_display_name_ = "Test Service" def __init__(self,args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.running = False def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) self.running = False def SvcDoRun(self): servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_,'')) self.running = True self.main() def main(self): while self.running: logging.debug("looped") time.sleep(2) if __name__ == '__main__': try: win32serviceutil.HandleCommandLine(OnePrintService) except Exception as e: print(e)
复现步骤
- 打开命令提示符
- 切换到脚本目录:
cd C:\new\directory\ - 执行安装命令:
python my_service.py install - 启动服务:
python my_service.py start - 等待几秒确认日志输出
- 停止服务:
python my_service.py stop(取消Fernet注释后此步骤报错)
解决方法
1. 对齐Python环境与依赖版本
Windows服务默认使用系统级Python环境,需确保服务环境与开发环境的cryptography版本完全一致:
- 用服务使用的Python解释器执行:
python -m pip list,记录cryptography版本 - 在自定义模块开发环境中安装同版本:
python -m pip install cryptography==<匹配版本号> - 避免跨环境版本差异导致的依赖冲突
2. 延迟导入Fernet模块
将Fernet的导入从全局移到服务运行的主逻辑中,规避服务初始化阶段的环境冲突:
# 全局部分不要导入Fernet def main(self): # 在主循环内或首次需要时导入 from cryptography.fernet import Fernet while self.running: logging.debug("looped") time.sleep(2)
3. 提升服务权限
Windows服务默认以LocalSystem账户运行,可能无权限读取虚拟环境或用户目录下的依赖文件:
- 打开服务管理器(
services.msc),找到Test Service - 右键→属性→登录,选择「此账户」,输入拥有本地管理员权限的账户信息
- 重启服务后测试停止命令
4. 打包时强制包含cryptography依赖
若使用pyinstaller打包,需确保cryptography的二进制文件被正确打包:
- 打包命令添加参数:
pyinstaller --hidden-import cryptography.fernet your_script.py - 检查打包后的目录,确认
cryptography相关的.pyd文件存在于Lib\site-packages\cryptography路径下 - 打包前确保自定义模块的依赖已完整安装到打包环境中
5. 修复cryptography二进制依赖
cryptography在Windows上依赖openssl相关库,重新安装预编译版本可解决文件损坏问题:
- 卸载现有版本:
python -m pip uninstall -y cryptography - 安装预编译版本:
python -m pip install cryptography --only-binary :all:
内容的提问来源于stack exchange,提问作者Shmack
相关产品推荐
相关产品推荐

