使用 python 写 COM
Python 支持Com调用(client com) 以及撰写COM 组件(server com).
1. com 调用示例(使用Windows Media Player 播放音乐)
2. com server 的编写
主要可以参考 << Python Programming on Win32 之 Chapter 12 Advanced Python and COM http://oreilly.com/catalog/pythonwin32/chapter/ch12.html >>
示例(分割字符串)
- 代码
- 注册/注销Com
- 使用COM
可以在python 命令行下运行
3. python server com 原理
其实在注册表中查找到python com 的实现内幕
local server 通过localserver.py 实现
com 对应的python 源文件信息在 PythonCOMPath & PythonCOM
4. 使用问题
用PHP 或者 c 调用com 的时候
pythoncom error: PythonCOM Server - The 'win32com.server.policy' module could not be loaded.
<type 'exceptions.ImportError'>: No module named server.policy pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)
可以通过2种方式解决:
a. 设置环境 PYTHONHOME = D:\usr\Python
另外在c ++ 使用python 的时候, 如果import module 出现错误 'import site' failed; use -v for traceback 的话, 也可以通过设置这个变量解决.
b. 为com 生产exe, dll 可执行文件, setup.py 代码如下 :
ref:
http://oreilly.com/catalog/pythonwin32/chapter/ch12.html
http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx
1. com 调用示例(使用Windows Media Player 播放音乐)
from
win32com.client
import
Dispatch
mp = Dispatch( " WMPlayer.OCX " )
tune = mp.newMedia( " C:/WINDOWS/system32/oobe/images/title.wma " )
mp.currentPlaylist.appendItem(tune)
mp.controls.play()
mp = Dispatch( " WMPlayer.OCX " )
tune = mp.newMedia( " C:/WINDOWS/system32/oobe/images/title.wma " )
mp.currentPlaylist.appendItem(tune)
mp.controls.play()
2. com server 的编写
主要可以参考 << Python Programming on Win32 之 Chapter 12 Advanced Python and COM http://oreilly.com/catalog/pythonwin32/chapter/ch12.html >>
示例(分割字符串)
- 代码
class
PythonUtilities:
_public_methods_ = [ ' SplitString ' ]
_reg_progid_ = " PythonDemos.Utilities "
# NEVER copy the following ID
# Use "print pythoncom.CreateGuid()" to make a new one.
_reg_clsid_ = " {41E24E95-D45A-11D2-852C-204C4F4F5020} "
def SplitString(self, val, item = None):
import string
if item != None: item = str(item)
return string.split(str(val), item)
# Add code so that when this script is run by
# Python.exe, it self-registers.
if __name__ == ' __main__ ' :
print " Registering COM server "
import win32com.server.register
win32com.server.register.UseCommandLine(PythonUtilities)
_public_methods_ = [ ' SplitString ' ]
_reg_progid_ = " PythonDemos.Utilities "
# NEVER copy the following ID
# Use "print pythoncom.CreateGuid()" to make a new one.
_reg_clsid_ = " {41E24E95-D45A-11D2-852C-204C4F4F5020} "
def SplitString(self, val, item = None):
import string
if item != None: item = str(item)
return string.split(str(val), item)
# Add code so that when this script is run by
# Python.exe, it self-registers.
if __name__ == ' __main__ ' :
print " Registering COM server "
import win32com.server.register
win32com.server.register.UseCommandLine(PythonUtilities)
- 注册/注销Com
Command-Line Option |
Description |
---|---|
|
The default is to register the COM objects. |
|
Unregisters the objects. This removes all references to the objects from the Windows registry. |
|
Registers the COM servers in debug mode. We discuss debugging COM servers later in this chapter. |
|
Register (or unregister) the object quietly (i.e., don't report success). |
- 使用COM
可以在python 命令行下运行
>>>
import
win32com.client
>>> s = win32com.client.Dispatch( " PythonDemos.Utilities " )
>>> s.SplitString( " a,b,c " , " , " )
((u ' a ' , u ' a,b,c ' ),)
>>>
>>> s = win32com.client.Dispatch( " PythonDemos.Utilities " )
>>> s.SplitString( " a,b,c " , " , " )
((u ' a ' , u ' a,b,c ' ),)
>>>
3. python server com 原理
其实在注册表中查找到python com 的实现内幕
Windows Registry Editor Version
5.00
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020} ]
@ = " PythonDemos.Utilities "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Debugging ]
@ = " 0 "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories ]
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories\{B3EF80D0-68E2-11D0-A689-00C04FD658FF} ]
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\InprocServer32 ]
@ = " pythoncom25.dll "
" ThreadingModel " = " both "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\LocalServer32 ]
@ = " D:\\usr\\Python\\pythonw.exe \ " D:\\usr\\Python\\lib\\site-packages\\win32com\\server\\localserver.py\ " {41E24E95-D45A-11D2-852C-204C4F4F5020} "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\ProgID ]
@ = " PythonDemos.Utilities "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOM ]
@ = " PythonDemos.PythonUtilities "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOMPath ]
@ = " D:\\ "
inproc server 是通过pythoncom25.dll 实现
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020} ]
@ = " PythonDemos.Utilities "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Debugging ]
@ = " 0 "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories ]
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\Implemented Categories\{B3EF80D0-68E2-11D0-A689-00C04FD658FF} ]
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\InprocServer32 ]
@ = " pythoncom25.dll "
" ThreadingModel " = " both "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\LocalServer32 ]
@ = " D:\\usr\\Python\\pythonw.exe \ " D:\\usr\\Python\\lib\\site-packages\\win32com\\server\\localserver.py\ " {41E24E95-D45A-11D2-852C-204C4F4F5020} "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\ProgID ]
@ = " PythonDemos.Utilities "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOM ]
@ = " PythonDemos.PythonUtilities "
[ HKEY_CLASSES_ROOT\CLSID\{41E24E95-D45A-11D2-852C-204C4F4F5020}\PythonCOMPath ]
@ = " D:\\ "
local server 通过localserver.py 实现
com 对应的python 源文件信息在 PythonCOMPath & PythonCOM
4. 使用问题
用PHP 或者 c 调用com 的时候
<?
php
$com = new COM( " PythonDemos.Utilities " );
$rs = $com -> SplitString( " a b c " );
foreach ( $rs as $r )
echo $r . " \n " ;
?>
会碰到下面的一些错误.
$com = new COM( " PythonDemos.Utilities " );
$rs = $com -> SplitString( " a b c " );
foreach ( $rs as $r )
echo $r . " \n " ;
?>
pythoncom error: PythonCOM Server - The 'win32com.server.policy' module could not be loaded.
<type 'exceptions.ImportError'>: No module named server.policy pythoncom error: CPyFactory::CreateInstance failed to create instance. (80004005)
可以通过2种方式解决:
a. 设置环境 PYTHONHOME = D:\usr\Python
另外在c ++ 使用python 的时候, 如果import module 出现错误 'import site' failed; use -v for traceback 的话, 也可以通过设置这个变量解决.
b. 为com 生产exe, dll 可执行文件, setup.py 代码如下 :
from
distutils.core
import
setup
import py2exe
import sys
import shutil
# Remove the build tree ALWAYS do that!
shutil.rmtree( " build " , ignore_errors = True)
# List of modules to exclude from the executable
excludes = [ " pywin " , " pywin.debugger " , " pywin.debugger.dbgcon " , " pywin.dialogs " , " pywin.dialogs.list " ]
# List of modules to include in the executable
includes = [ " win32com.server " ]
# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
try :
# if this doesn't work, try import modulefinder
import py2exe.mf as modulefinder
import win32com
for p in win32com. __path__ [ 1 :]:
modulefinder.AddPackagePath( " win32com " , p)
for extra in [ " win32com.shell " , " win32com.server " ]: # ,"win32com.mapi"
__import__ (extra)
m = sys.modules[extra]
for p in m. __path__ [ 1 :]:
modulefinder.AddPackagePath(extra, p)
except ImportError:
# no build path setup, no worries.
pass
# Set up py2exe with all the options
setup(
options = { " py2exe " : { " compressed " : 2 ,
" optimize " : 2 ,
# "bundle_files": 1,
" dist_dir " : " COMDist " ,
" excludes " : excludes,
" includes " : includes}},
# The lib directory contains everything except the executables and the python dll.
# Can include a subdirectory name.
zipfile = None,
com_server = [ 'PythonDemos ' ], # 文件名!!
)
import py2exe
import sys
import shutil
# Remove the build tree ALWAYS do that!
shutil.rmtree( " build " , ignore_errors = True)
# List of modules to exclude from the executable
excludes = [ " pywin " , " pywin.debugger " , " pywin.debugger.dbgcon " , " pywin.dialogs " , " pywin.dialogs.list " ]
# List of modules to include in the executable
includes = [ " win32com.server " ]
# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
try :
# if this doesn't work, try import modulefinder
import py2exe.mf as modulefinder
import win32com
for p in win32com. __path__ [ 1 :]:
modulefinder.AddPackagePath( " win32com " , p)
for extra in [ " win32com.shell " , " win32com.server " ]: # ,"win32com.mapi"
__import__ (extra)
m = sys.modules[extra]
for p in m. __path__ [ 1 :]:
modulefinder.AddPackagePath(extra, p)
except ImportError:
# no build path setup, no worries.
pass
# Set up py2exe with all the options
setup(
options = { " py2exe " : { " compressed " : 2 ,
" optimize " : 2 ,
# "bundle_files": 1,
" dist_dir " : " COMDist " ,
" excludes " : excludes,
" includes " : includes}},
# The lib directory contains everything except the executables and the python dll.
# Can include a subdirectory name.
zipfile = None,
com_server = [ 'PythonDemos ' ], # 文件名!!
)
ref:
http://oreilly.com/catalog/pythonwin32/chapter/ch12.html
http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx