我有一个Windows 7环境,我需要使用Python 3.4开发一个Python Windows服务。 我正在使用pywin32的win32service模块来设置服务和大部分的钩子似乎工作正常。
问题是当我试图从源代码运行服务(使用python service.py install然后python service.py start )。 这使用PythonService.exe托pipeservice.py – 但我使用venv虚拟环境和脚本无法find它的模块(使用python service.py debug发现错误信息)。
Pywin32安装在virtualenv中,并查看PythonService.exe的源代码,它在python34.dll中dynamic链接,导入我的service.py并调用它。
如何在运行我的service.py时使PythonService.exe使用我的virtualenv?
如何检查远程服务器上是否使用batch file打开端口,而不使用第三方软件?
py2exe:build立可执行文件挂起
使用JavaScript开发Windows应用程序
在Windows 2008 R2中注册我的密码filter后没有结果
在Windows中使用更快的rcnn pycaffe失败与boost python错误
Python:在Windows上相当于signal.pause()
42传递给TerminateProcess,有时GetExitCodeProcess返回0
应用程序保持closures与2012年
在Windows Java SecureRandom.generateSeed失败:意外的CryptoAPI失败
取消KeyUP事件的处理程序? VB.NET
非常感谢发布这个问题和解决方案。 我采取了一个稍微不同的方法,这也可能是有用的。 找到Python服务的工作技巧是非常困难的,更不用说用virtualenv来完成了。 无论如何…
脚步
这是使用Windows 7 x64,Python 3.5.1 x64,pywin32-220(或pypiwin32-219)。
创建一个virtualenv。 C:python35python -m venv myvenv
激活virtualenv。 call myvenvscriptsactivate.bat
安装pywin32,或者:
从Pypi: pip install pypiwin32 ,
从http://www.lfd.uci.edu/~gohlke/pythonlibs/:pip pip install pathtopywin32.whl
运行安装后脚本python myvenvScriptspywin32_postinstall.py -install 。
该脚本在系统中注册该DLL,并将它们复制到C:WindowsSystem32 。 该DLL的名称为pythoncom35.dll和pywintypes35.dll 。 所以在同一个主要的Python版本发布的同一台机器上的虚拟环境将共享这些…这是一个小小的折衷:)
将myvenvLibsite-packageswin32pythonservice.exe到myvenvScriptspythonservice.exe
在服务类(无论win32serviceutil.ServiceFramework的子类)上,将类属性_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业务,则不能从venvLibsite-packageswin32的* .pyd文件作为脚本中的模块导入。 例如,需要允许import servicemanager ; 因为servicemanager.pyd不在软件包中作为.py文件,并具有一些很酷的Windows事件日志功能。
我接受的答案的一个问题是,我不知道如何让它准确地拿起使用setup.py develop时创建的package.egg-link路径。 这些.egg链接文件包含不在myvenvLibsite-packages下的virtualenv中的包的路径。
如果一切顺利,应该可以安装,启动和测试示例win32服务(从激活的virtualenv中的管理提示符):
python venvLibsite-packageswin32DemosservicepipeTestService.py install python venvLibsite-packageswin32DemosservicepipeTestService.py start python venvLibsite-packageswin32DemosservicepipeTestServiceClient.py
服务环境
所有这一切的另一个重要的注意事项是,该服务将在一个完全独立的环境中执行python代码,以便运行python myservice.py debug 。 因此,例如运行服务时, os.environ['VIRTUAL_ENV']将为空。 这可以通过以下任一方式处理:
在脚本中设置环境变量,例如
按照接受的答案中所述,查找从sys.exe可执行文件开始的当前路径。
使用该路径来查找配置文件。
阅读配置文件,并把它们放在os.environ的环境中。
请参阅从Windows服务访问环境变量,以便使用regedit.exe手动执行此操作
请参阅REG在命令行中添加一个REG_MULTI_SZ多行注册表值 。
在虚拟环境被添加到Python 3.3之前,它似乎用来与virtualenv模块正常工作。 有轶事证据(见这个答案: https : site.py )Python的site.py用来从可执行文件向上看,直到找到一个满足导入的目录。 然后,它将用于sys.prefix ,这足以让PythonService.exe找到它所在的virtualenv并使用它。
如果这是行为,那么site.py不会再引入venv模块了。 相反,它看起来只有pyvenv.cfg文件的一个级别,并在这种情况下配置虚拟环境。 这当然不适用于位于站点包下的pywin32模块中的PythonService.exe。
为了解决这个问题,我调整了原始virtualenv模块的activate_this.py代码(请参阅https://stackoverflow.com/a/33637378/1055722 )。 它被用来引导嵌入在可执行文件(这是PythonService.exe的情况下)的解释器,使用virtualenv。 不幸的是, venv不包括这个。
这是为我工作的。 请注意,假设虚拟环境名为my-venv,位于源代码位置的上一级。
import os import sys if sys.executable.endswith("PythonService.exe"): # Change current working directory from PythonService.exe location to something better. service_directory = os.path.dirname(__file__) source_directory = os.path.abspath(os.path.join(service_directory,"..")) os.chdir(source_directory) sys.path.append(".") # Adapted from virtualenv's activate_this.py # Manually activate a virtual environment inside an already initialized interpreter. old_os_path = os.environ['PATH'] venv_base = os.path.abspath(os.path.join(source_directory,"..","my-venv")) os.environ['PATH'] = os.path.join(venv_base,"Scripts") + os.pathsep + old_os_path site_packages = os.path.join(venv_base,'Lib','site-packages') prev_sys_path = list(sys.path) import site site.addsitedir(site_packages) sys.real_prefix = sys.prefix sys.prefix = venv_base new_sys_path = [] for item in list(sys.path): if item not in prev_sys_path: new_sys_path.append(item) sys.path.remove(item) sys.path[:0] = new_sys_path
另外一个因素是我的麻烦 – pywin32有一个新的pypi轮子,由Twisted提供,使用pip更容易安装。 该包中的PythonService.exe与使用easy_install将正式的win32 exe软件包安装到虚拟环境中时得到的结果相比,性能异常(在调用时找不到pywin32 dll)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。