我有一個使用win32com庫來控制iTunes程序,但一直有一些問題得到它編譯成可執行文件。這個問題似乎圍繞着使用DispatchWithEvents
代替Dispatch
。我創建了一個非常簡單的程序來說明我的問題:py2exe/pyinstaller和DispatchWithEvents
import win32com.client
win32com.client.gencache.is_readonly = False #From py2exe wiki
class ITunesEvents(object):
def __init__(self): self.comEnabled = True
def OnCOMCallsDisabledEvent(self, reason): self.comEnabled = False
def OnCOMCallsEnabledEvent(self): self.comEnabled = True
# The first line works in the exe, the second doesn't.
itunes = win32com.client.Dispatch("iTunes.Application")
#itunes = win32com.client.DispatchWithEvents("iTunes.Application", ITunesEvents)
lib = getattr(itunes, "LibraryPlaylist")
src = getattr(lib, "Source")
playlists = getattr(src, "Playlists")
print "Found %i playlists." % getattr(playlists, "Count")
使用Dispatch
,程序編譯和運行正常。使用DispatchWithEvents
,從命令行調用的時候,程序運行良好,但生產運行exe文件時出現以下錯誤:
Traceback (most recent call last):
File "sandbox.py", line 16, in <module>
itunes = win32com.client.DispatchWithEvents("iTunes.Application", ITunesEvents)
File "win32com\client\__init__.pyc", line 252, in DispatchWithEvents
File "win32com\client\gencache.pyc", line 520, in EnsureModule
File "win32com\client\gencache.pyc", line 287, in MakeModuleForTypelib
File "win32com\client\makepy.pyc", line 259, in GenerateFromTypeLibSpec
File "win32com\client\gencache.pyc", line 141, in GetGeneratePath
IOError: [Errno 2] No such file or directory: '[distDir]\\library.zip\\win32com\\gen_py\\__init__.py'
我使用PyInstaller,這給出了一個類似的錯誤也試過:
File "<string>", line 16, in <module>
File "[outDir]/win32com.client", line 252, in DispatchWithEvents
File "[outDir]/win32com.client.gencache", line 520, in EnsureModule
File "[outDir]/win32com.client.gencache", line 287, in MakeModuleForTypelib
File "[outDir]/win32com.client.makepy", line 286, in GenerateFromTypeLibSpec
File "[outDir]/win32com.client.gencache", line 550, in AddModuleToCache
File "[outDir]/win32com.client.gencache", line 629, in _GetModule
File "[pyinstallerDir]\iu.py", line 455, in importHook
raise ImportError, "No module named %s" % fqname
ImportError: No module named win32com.gen_py.9E93C96F-CF0D-43F6-8BA8-B807A3370712x0x1x13
我知道我可以手動添加類型庫在我setup.py
文件,但我想不用重新編譯,所以我寧願動態地創建與運行不同版本的iTunes計算機上的代碼。如果沒有辦法通過setup/spec來做到這一點,也許有另一種方法來加載事件?謝謝。
增加:
感謝瑞安,我發現我可以把生成的PY文件和一個小挖之後,能夠拿出以下。
將生成的py文件(來自makepy.py
)並將其重命名爲cominterface.py
。然後,您需要執行以下操作以實際創建具有事件處理程序的COM對象。
import cominterface
from types import ClassType
from win32com.client import EventsProxy, _event_setattr_
class ItunesEvents:
'''iTunes events class. See cominterface for details.'''
def OnPlayerPlayEvent(self, t):print "Playing..."
def OnPlayerStopEvent(self, t): print "Stopping..."
itunes = cominterface.iTunesApp()
rClass = ClassType("COMEventClass", (itunes.__class__, itunes.default_source, ItunesEvents), {'__setattr__': _event_setattr_})
instance = rClass(itunes._oleobj_)
itunes.default_source.__init__(instance, instance)
#ItunesEvents.__init__(instance) #Uncomment this line if your events class has __init__.
itunes = EventsProxy(instance)
然後你可以去做你的生意。
I我認爲這可行,但我似乎無法弄清楚如何明確地調用接口,特別是使用事件。我有''Dispatch''工作,但後來意識到這只是調用win32com正常。有沒有關於如何做到這一點的信息? – jeffaudio 2010-04-26 17:14:29