簡體   English   中英

py2exe / pyinstaller和DispatchWithEvents

[英]py2exe/pyinstaller and DispatchWithEvents

我有一個使用win32com庫來控制iTunes的程序,但是在編譯成可執行文件時遇到了一些問題。 問題似乎圍繞使用DispatchWithEvents而不是Dispatch 我創建了一個非常簡單的程序來說明我的問題:

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文件中手動添加typelib,但是我想在不同版本的iTunes的計算機上運行代碼而不重新編譯,所以我更願意動態創建它。 如果使用setup / spec無法做到這一點,可能還有另一種加載事件的方法嗎? 謝謝。


加成:

感謝Ryan,我發現我可以使用生成的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)

然后你可以開展你的業務。

我遇到了完全相同的錯誤。 這個鏈接讓我朝着正確的方向 - > http://www.py2exe.org/index.cgi/UsingEnsureDispatch然而它提到:NB你必須確保python ... \\ win32com.client.gen_py目錄不允許在%temp%中創建緩存,這有點令人困惑。 為我解決的是將“C:\\ Python26 \\ Lib \\ site-packages \\ win32com \\ gen_py”重命名為“C:\\ Python26 \\ Lib \\ site-packages \\ win32com \\ gen_pybak”(運行py2exe時)

是正式的做法。

(編輯:從上面的鏈接復制的逐字例子)

import win32com.client
if win32com.client.gencache.is_readonly == True:

    #allow gencache to create the cached wrapper objects
    win32com.client.gencache.is_readonly = False

    # under p2exe the call in gencache to __init__() does not happen
    # so we use Rebuild() to force the creation of the gen_py folder
    win32com.client.gencache.Rebuild()

    # NB You must ensure that the python...\win32com.client.gen_py dir does not exist
    # to allow creation of the cache in %temp%

# Use SAPI speech through IDispatch
from win32com.client.gencache import EnsureDispatch
from win32com.client import constants
voice = EnsureDispatch("Sapi.SpVoice", bForDemand=0)
voice.Speak( "Hello World.", constants.SVSFlagsAsync )

我建議不要依賴緩存,而是進入本地緩存目錄,將生成的文件復制到本地項目文件中,並將其命名為ITunesInterface.py,並明確地調用它。 這將使py2exe將其拉入您的編譯應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM