py2exe / pyinstaller и 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 

Я знаю, что могу вручную добавить typelib в свой файл setup.py , но я бы хотел запустить код на компьютерах с разными версиями iTunes без перекомпиляции, поэтому я бы предпочел динамически его создать. Если нет способа сделать это с помощью установки / спецификации, возможно, есть другой способ загрузить события? Благодарю.


Дополнение:

Благодаря Райану, я обнаружил, что могу взять сгенерированный файл 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) 

Тогда вы можете заниматься своим бизнесом.

  • Ошибка xlПример не определен в Python win32com
  • Графики из Excel в PowerPoint с Python
  • win32com.client.Dispatch + Cherrypy = CoInitialize не был вызван
  • Как я могу программно использовать средство проверки правописания / грамматики Microsoft Word?
  • Чтение событий Outlook через Python
  • Python - запустить макрос Excel
  • Экспорт диаграмм из Excel в виде изображений с использованием Python
  • Настройка свойства с помощью win32com
  • 3 Solutions collect form web for “py2exe / pyinstaller и DispatchWithEvents”

    Вместо того, чтобы в зависимости от кеша, я бы рекомендовал зайти в локальный каталог кеша, скопировать сгенерированный файл в файл локального проекта и называть его чем-то вроде ITunesInterface.py и называть это явно. Это заставит py2exe втянуть его в ваше скомпилированное приложение.

    Я испытывал ту же ошибку. Эта ссылка поставила меня в правильном направлении -> 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 ) 
    Python - лучший язык программирования в мире.