Python 支持Com调用(client com) 以及撰写COM 组件(server com).
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()
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)
- 注册/注销Com
Command-Line Option
|
Description
|
|
The default is to register the COM objects.
|
--unregister
|
Unregisters the objects. This removes all references to the objects from the Windows registry.
|
--debug
|
Registers the COM servers in debug mode. We discuss debugging COM servers later in this chapter.
|
--quiet
|
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'),)
>>>
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 实现
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";
?>
会碰到下面的一些错误.
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'], # 文件名!!
)
ref:
http://oreilly.com/catalog/pythonwin32/chapter/ch12.html http://blog.donews.com/limodou/archive/2005/09/02/537571.aspx