我有一个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中,导入my service.py并调用它。
如何让PythonService.exe在运行service.py时使用我的virtualenv?
非常感谢你发布这个问题和解决方案。我采取了一种稍微不同的方法,这可能也是有用的。很难找到Python服务的工作技巧,更不用说使用virtualenv了。不管怎样。。。
台阶
这使用的是Windows 7 x64、Python 3.5.1 x64、pywin32-220(或pypiwin32-219)。
C:\Python35\python -m venv myvenv
call myvenv\scripts\activate.bat
pip install pypiwin32
pip install path\to\pywin32.whl
python myvenv\Scripts\pywin32_postinstall.py -install
。C:\Windows\System32
。DLL名为pythoncom35.dll
和pywintypes35.dll
。所以,在同一台机器上的同一个主要Python点发行版上的虚拟环境将共享这些。。。这是一个小小的折衷:)myvenv\Lib\site-packages\win32\pythonservice.exe
复制到myvenv\Scripts\pythonservice.exe
_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文件中导入脚本中的模块。例如,它需要allowimport servicemanager
;因为servicemanager.pyd
不作为.py文件存在于包中,并且具有一些很酷的Windows事件日志功能。我在接受答案时遇到的一个问题是,我不知道如何让它准确地获取package.egg-link路径,这些路径是在使用
setup.py develop
时创建的。当包不在myvenv\Lib\site-packages
下的virtualenv中时,这些.egg链接文件包含包的路径。如果一切顺利,应该可以安装、启动和测试示例win32服务(从激活的virtualenv中的管理提示):
服务环境
这一切中的另一个重要注意事项是,服务将在与您可能运行的
python myservice.py debug
完全不同的环境中执行python代码。例如,运行服务时os.environ['VIRTUAL_ENV']
将为空。这可以通过以下任一方式处理:os.environ
的环境中。对于2018年的读者来说,我在上面的任何一个解决方案(Win10,Python 3.6)上都没有任何运气——所以我就是这么做的。工作目录在启动时位于site packages/win32中,因此在尝试导入任何项目代码之前,需要更改工作目录并修复sys.path。假设venv位于您的项目目录中,否则您可能只需要硬编码一些路径:
在将虚拟环境添加到Python 3.3之前,这似乎用于正确处理
virtualenv
模块。有传闻证据(见这个答案:https://stackoverflow.com/a/12424980/1055722)表明,Python的site.py
用于从可执行文件向上查找,直到找到满足导入的目录。然后,它会将其用于sys.prefix
,这就足以让PythonService.exe找到它所在的virtualenv并使用它。如果这是行为,那么随着
venv
模块的引入,site.py
似乎不再这样做了。相反,它会向上查找一个pyvenv.cfg
文件,并仅在这种情况下为虚拟环境进行配置。当然,这对于PythonService.exe不起作用,它被隐藏在站点包下的pywin32模块中。为了解决这个问题,我修改了原始
activate_this.py
模块附带的virtualenv
代码(请参阅这个答案:https://stackoverflow.com/a/33637378/1055722)。它用于引导嵌入可执行文件(PythonService.exe就是这样)中的解释器使用virtualenv。不幸的是,venv
不包括这个。这是对我有用的。注意,这假设虚拟环境名为my venv,位于源代码位置上方一层。
我遇到麻烦的另一个因素是,pywin32有一个新的pypi控制盘,它是由Twisted人员提供的,使pip更易于安装。该包中的PythonService.exe与使用easy_install将正式的win32 exe包安装到虚拟环境中时获得的pywin32 dll相比,运行异常(调用时找不到pywin32 dll)。
相关问题 更多 >
编程相关推荐