سؤال

لديّ برنامج يستخدم مكتبة 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 دون إعادة ترجمة ، لذلك أفضل إنشاءه ديناميكيًا. إذا لم تكن هناك طريقة للقيام بذلك باستخدام الإعداد/المواصفات ، فربما هناك طريقة أخرى لتحميل الأحداث؟ شكرًا.


إضافة:

بفضل 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)

ثم يمكنك القيام بعملك.

هل كانت مفيدة؟

المحلول

بدلاً من الاعتماد على ذاكرة التخزين المؤقت ، أوصي بالذهاب إلى دليل ذاكرة التخزين المؤقت المحلي ، ونسخ الملف الذي تم إنشاؤه إلى ملف المشروع المحلي الخاص بك ، وتسمية شيء مثل iTunesinterface.py ، والاتصال بذلك بشكل صريح. هذا سيجعل py2exe يسحبه إلى التطبيق المترجم.

نصائح أخرى

كنت أعاني من نفس الخطأ بالضبط. هذا الرابط وضعني في الاتجاه الصحيح ->http://www.py2exe.org/index.cgi/usingensureSureSpatchومع ذلك ، يذكر أن: NB يجب عليك التأكد من أن Python ... win32com.client.gen_py dir غير موجود للسماح بإنشاء ذاكرة التخزين المؤقت ٪ ٪ 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 )
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top