使用 python 写 COM

使用 python 写 COM
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 

你可能感兴趣的:(使用 python 写 COM)