我有一个Windows 7环境,我需要使用Python 3.4开发Python Windows服务.我正在使用pywin32的win32service模块来设置服务,大多数钩子似乎都正常工作.
问题是当我尝试从源代码运行服务时(使用python service.py install
后跟python service.py start
).这使用PythonService.exe来托管service.py - 但我使用的是venv虚拟环境,脚本无法找到它的模块(发现错误信息python service.py debug
).
Pywin32安装在virtualenv中,在查看PythonService.exe的源代码时,它在Python34.dll中动态链接,导入我的service.py并调用它.
运行service.py时如何让PythonService.exe使用我的virtualenv?
非常感谢您发布此问题和解决方案.我采取了一种稍微不同的方法,这也可能有用.很难找到Python服务的工作技巧,更不用说使用virtualenv了.无论如何...
脚步这是使用Windows 7 x64,Python 3.5.1 x64,pywin32-220(或pypiwin32-219).
打开管理员命令提示符.
创建一个virtualenv. C:\Python35\python -m venv myvenv
激活virtualenv. call myvenv\scripts\activate.bat
安装pywin32,或者:
来自Pypi : pip install pypiwin32
,
来自http://www.lfd.uci.edu/~gohlke/pythonlibs/:pip install path\to\pywin32.whl
运行安装后脚本python myvenv\Scripts\pywin32_postinstall.py -install
.
此脚本在系统中注册DLL,并将其复制到C:\Windows\System32
.DLL的名称pythoncom35.dll
和pywintypes35.dll
.因此,在相同主要Python点发布的同一台机器上的虚拟环境将共享这些...这是一个小的权衡:)
复制myvenv\Lib\site-packages\win32\pythonservice.exe
到myvenv\Scripts\pythonservice.exe
在服务类(无论子类win32serviceutil.ServiceFramework)上,将class属性设置_exe_path_
为指向此重定位的exe.这将成为服务binPath.例如:_exe_path_ = os.path.join(*[os.environ['VIRTUAL_ENV'], 'Scripts', 'pythonservice.exe'])
.
讨论
我认为为什么这样做是因为Python向上查找Libs文件夹的位置并基于它设置包导入路径,类似于接受的答案.当pythonservice.exe位于原始位置时,这似乎并不顺利.
它还解决了DLL链接问题(可从http://www.dependencywalker.com/上的depends.exe发现).如果没有整理DLL业务,将无法从venv\Lib\site-packages\win32
脚本中的模块中导出*.pyd文件.例如,它需要允许import servicemanager
; 因为servicemanager.pyd
不在包中作为.py文件,并且具有一些很酷的Windows事件日志功能.
我接受的答案之一就是我无法弄清楚如何准确地接受使用时创建的package.egg-link路径setup.py develop
.这些.egg-link文件包含该软件包的路径,当它不在virtualenv下时myvenv\Lib\site-packages
.
如果一切顺利,应该可以安装,启动和测试示例win32服务(从激活的virtualenv中的Admin提示符):
python venv\Lib\site-packages\win32\Demos\service\pipeTestService.py install python venv\Lib\site-packages\win32\Demos\service\pipeTestService.py start python venv\Lib\site-packages\win32\Demos\service\pipeTestServiceClient.py服务环境
所有这一切的另一个重要注意事项是服务将在一个完全独立的环境中执行python代码到你可能运行的代码python myservice.py debug
.因此,例如os.environ['VIRTUAL_ENV']
在运行服务时将为空.这可以通过以下任一方式处理:
从脚本内部设置环境变量,例如
查找从sys.executable开始的当前路径,如接受的答案中所述.
使用该路径查找配置文件.
阅读配置文件并将其放入环境中os.environ
.
使用环境变量向服务添加注册表项.
有关使用regedit.exe手动执行此操作的信息,请参阅从Windows服务访问环境变量
有关使用命令行执行此操作,请参阅REG添加REG_MULTI_SZ多行注册表值.