将Python作为Windows服务运行:调用自定义模块脚本失败问题
我碰到好多开发者在把Python程序做成Windows服务时都遇到过这个问题——基础服务能正常运行,但一导入自己写的模块就报错。结合你描述的情况,大概率是服务运行时的工作目录和脚本所在目录不匹配,或者Python的模块搜索路径没包含你的自定义模块位置,给你几个实用的解决步骤:
1. 强制把脚本目录加入Python搜索路径
Windows服务默认的工作目录是C:\Windows\System32,而你的modules文件夹肯定和服务脚本在同一个目录下,所以Python根本找不到它。在服务代码的最开头加上这段代码,把脚本所在的绝对路径加入sys.path:
import os import sys # 获取当前服务脚本的绝对路径 script_dir = os.path.dirname(os.path.abspath(__file__)) # 将脚本目录添加到Python模块搜索路径的最前面 if script_dir not in sys.path: sys.path.insert(0, script_dir)
2. 确认你的自定义模块结构正确
如果modules是一个文件夹(包),一定要确保里面有__init__.py文件(可以是空文件),这样Python才会把它识别为合法的包。如果是单个modules.py文件,那from modules import copy_log的写法是对的;如果是文件夹包,要确保copy_log函数在modules/__init__.py里,或者在modules/copy_log.py里(这时候要写成from modules.copy_log import xxx)。
3. 加日志排查具体错误
有时候导入失败的具体原因看不到,建议在服务的运行逻辑里加异常捕获,把错误信息写到日志文件里,方便定位问题:
比如在TestService的SvcDoRun方法里修改:
def SvcDoRun(self): self.ReportServiceStatus(win32service.SERVICE_RUNNING) # 提前定义好日志路径 log_path = os.path.join(script_dir, 'service_error.log') try: # 这里调用你的自定义模块功能 copy_log() except Exception as e: # 把异常信息写入日志 with open(log_path, 'a', encoding='utf-8') as f: f.write(f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 异常信息:{str(e)}\n") # 保持服务运行的等待逻辑 win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
4. 安装服务的小细节
安装服务时一定要用管理员权限打开命令行,最好用脚本的绝对路径来执行安装命令,比如:
python "C:\path\to\your\service_script.py" install
避免因为相对路径导致服务找不到脚本文件。
按照这几步来,基本就能解决自定义模块导入失败的问题了——大部分情况都是路径问题在搞鬼。
内容的提问来源于stack exchange,提问作者Bogdan C

