You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

引入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:05:11