One thing about it you need to read is this link.

I will try to answer shortly (finally not so short by the end...) your question, but I'm not a expert.

When you create a COM object with python, how python knows what methods and parameters are available for this object? This is related to the notion of early and late binding.

If you try to create a COM object you never used before with Dispatch, you won't know what is available with your object. If I do in a Jupyter QtConsole:

import win32com.client as win32
xl_dis = win32.Dispatch("Excel.Application")
xl_dis
Out[3]: <COMObject Excel.Application>

Then trying xl_dis. to see what I can do after, I won't get any choice. I'm in the case of a late binding, "python does not know what the object can do".

If I do the same thing with EnsureDispatch:

import win32com.client as win32
xl_ens = win32.gencache.EnsureDispatch("Excel.Application")
xl_ens
Out[3]: <win32com.gen_py.Microsoft Excel 14.0 Object Library._Application instance at 0x35671240>

First, you can see the difference on the output and then if I do xl_ens. I will get some methods and parameters available. I'm now in early binding and "python knows some of what the object can do".

What happens is that EnsureDispatch forces to run makepy.py at first (look in your folder Lib\site-packages\win32com\client) to create a folder in Lib\site-packages\win32com\gen_py containing python scripts with some methods and parameters related to this COM object.

Now, if you try again in a new console using Dispatch, you will get the exact same result. Indeed, after using EnsureDispatch, the folder created before in win32com\gen_py still exists and "python still knows what the object can do". To experiment it yourself, go to your folder \win32com\gen_py and delete the folder with excel information (for me, the name is 00020813-0000-0000-C000-000000000046x0x1x7, not sure it is the same for you).

Finally, one difference between both is mainly to force or not the early binding the first time you create a COM object, but if the folder related to your COM object already exist in \win32com\gen_py, then not much difference.

These two sentences of the link I gave:

To force the use of early binding to access COM objects, you must force the MakePy process in your code. Once you have ensured the MakePy support exists, use win32com.client.Dispatch() as usual. It always returns the MakePy-supported wrappers for your COM object.

To force the MakePy process, the win32com.client.gencache module is used. This module contains the code that manages the directory of MakePy-generated source files: the generated cache, or gencache. There are a number of useful functions in this module, and you are encouraged to browse the source file if you need to perform advanced management of these generated files.

kind of summary this.

The other alternative is to use dynamic such as win32.dynamic.Dispatch("Excel.Application") and you will always get a COM object in late binding.

Answer from Ben.T on Stack Overflow
🌐
GitHub
github.com › mhammond › pywin32 › blob › main › com › win32com › client › gencache.py
pywin32/com/win32com/client/gencache.py at main · mhammond/pywin32
# Our gencache is in a .zip file (and almost certainly readonly) # but no dicts file. That actually needn't be fatal for a frozen · # application. Assuming they call "EnsureModule" with the same · # typelib IDs they have been frozen with, that EnsureModule will ·
Author   mhammond
Top answer
1 of 2
53

One thing about it you need to read is this link.

I will try to answer shortly (finally not so short by the end...) your question, but I'm not a expert.

When you create a COM object with python, how python knows what methods and parameters are available for this object? This is related to the notion of early and late binding.

If you try to create a COM object you never used before with Dispatch, you won't know what is available with your object. If I do in a Jupyter QtConsole:

import win32com.client as win32
xl_dis = win32.Dispatch("Excel.Application")
xl_dis
Out[3]: <COMObject Excel.Application>

Then trying xl_dis. to see what I can do after, I won't get any choice. I'm in the case of a late binding, "python does not know what the object can do".

If I do the same thing with EnsureDispatch:

import win32com.client as win32
xl_ens = win32.gencache.EnsureDispatch("Excel.Application")
xl_ens
Out[3]: <win32com.gen_py.Microsoft Excel 14.0 Object Library._Application instance at 0x35671240>

First, you can see the difference on the output and then if I do xl_ens. I will get some methods and parameters available. I'm now in early binding and "python knows some of what the object can do".

What happens is that EnsureDispatch forces to run makepy.py at first (look in your folder Lib\site-packages\win32com\client) to create a folder in Lib\site-packages\win32com\gen_py containing python scripts with some methods and parameters related to this COM object.

Now, if you try again in a new console using Dispatch, you will get the exact same result. Indeed, after using EnsureDispatch, the folder created before in win32com\gen_py still exists and "python still knows what the object can do". To experiment it yourself, go to your folder \win32com\gen_py and delete the folder with excel information (for me, the name is 00020813-0000-0000-C000-000000000046x0x1x7, not sure it is the same for you).

Finally, one difference between both is mainly to force or not the early binding the first time you create a COM object, but if the folder related to your COM object already exist in \win32com\gen_py, then not much difference.

These two sentences of the link I gave:

To force the use of early binding to access COM objects, you must force the MakePy process in your code. Once you have ensured the MakePy support exists, use win32com.client.Dispatch() as usual. It always returns the MakePy-supported wrappers for your COM object.

To force the MakePy process, the win32com.client.gencache module is used. This module contains the code that manages the directory of MakePy-generated source files: the generated cache, or gencache. There are a number of useful functions in this module, and you are encouraged to browse the source file if you need to perform advanced management of these generated files.

kind of summary this.

The other alternative is to use dynamic such as win32.dynamic.Dispatch("Excel.Application") and you will always get a COM object in late binding.

2 of 2
17

Location of the generated cache may be in USER_PROFILE\AppData\Local\Temp\gen_py\PYTHON_VERSION\ . This can be useful if one wants to clear the cache.

🌐
GitHub
github.com › SublimeText › Pywin32 › blob › master › lib › x64 › win32com › client › gencache.py
Pywin32/lib/x64/win32com/client/gencache.py at master · SublimeText/Pywin32
# Our gencache is in a .zip file (and almost certainly readonly) # but no dicts file. That actually needn't be fatal for a frozen · # application. Assuming they call "EnsureModule" with the same · # typelib IDs they have been frozen with, that EnsureModule will ·
Author   SublimeText
🌐
Py2exe
py2exe.org › index.cgi › UsingEnsureDispatch
UsingEnsureDispatch - py2exe.org
1 import win32com.client 2 if win32com.client.gencache.is_readonly == True: 3 4 #allow gencache to create the cached wrapper objects 5 win32com.client.gencache.is_readonly = False 6 7 # under p2exe the call in gencache to __init__() does not happen 8 # so we use Rebuild() to force the creation of the gen_py folder 9 win32com.client.gencache.Rebuild() 10 11 # NB You must ensure that the python...\win32com.client.gen_py dir does not exist 12 # to allow creation of the cache in %temp% 13 14 # Use SAPI speech through IDispatch 15 from win32com.client.gencache import EnsureDispatch 16 from win32com.client import constants 17 voice = EnsureDispatch("Sapi.SpVoice", bForDemand=0) 18 voice.Speak( "Hello World.", constants.SVSFlagsAsync )
🌐
Microsoft Learn
learn.microsoft.com › en-us › answers › questions › 642324 › win32com-client-gencache-ensuredispatch-error
win32com.client.gencache.EnsureDispatch error - Microsoft Q&A
November 26, 2021 - #Get visio application import win32com.client as win32 visio = win32.gencache.EnsureDispatch('Visio.Application') visio.Visible = True input("Press enter to continue") stencilPath = "W:/Systeembeheer/Visio/BigBrother_Stencil.vssx" document = visio.Documents.Add("") stencil = visio.Documents.Open(stencilPath) page = document.Pages.Item(1)
🌐
GitHub
github.com › mhammond › pywin32 › issues › 1568
"win32com.client.gencache.EnsureDispatch" doesn't work on office 64bit · Issue #1568 · mhammond/pywin32
August 1, 2020 - d:\miniconda3\lib\site-packages\win32com\client\build.py in _ResolveType(typerepr, itypeinfo) 449 try: --> 450 resultTypeInfo = itypeinfo.GetRefTypeInfo(subrepr) 451 except pythoncom.com_error as details: com_error: (-2147319765, '找不到元素。', None, None) During handling of the above exception, another exception occurred: TypeError Traceback (most recent call last) <ipython-input-3-0b4e4188fb87> in <module> ----> 1 win32.gencache.EnsureDispatch('Excel.Application') d:\miniconda3\lib\site-packages\win32com\client\gencache.py in EnsureDispatch(prog_id, bForDemand) 539 disp = disp_class(disp._oleobj_) 540 except pythoncom.com_error: --> 541 raise TypeError("This COM object can not automate the makepy process - please run makepy manually for this object") 542 return disp 543 TypeError: This COM object can not automate the makepy process - please run makepy manually for this object`
Author   mhammond
🌐
GitHub
github.com › pyinstaller › pyinstaller › issues › 6257
genpy hook breaks win32com.client.gencache.EnsureDispatch() · Issue #6257 · pyinstaller/pyinstaller
September 29, 2021 - from win32com.client import gencache excel = gencache.EnsureDispatch("Excel.Application") if not input(">"): # this will generate a cache that is complete for this "if" branch, but incomplete for the "else" branch.
Author   pyinstaller
🌐
WMI
timgolden.me.uk › python › win32_how_do_i › generate-a-static-com-proxy.html
Generate a static COM proxy - Tim Golden's Python Stuff
import win32com.client xl = win32com.client.gencache.EnsureDispatch ("Excel.Application") print xl.__module__
Find elsewhere
🌐
DEV Community
dev.to › lukesavefrogs › basic-operations-4oom
Basic operations - DEV Community
November 2, 2022 - from win32com import client excel = client.gencache.EnsureDispatch('Excel.Application')
🌐
GitHub
github.com › SublimeText › Pywin32 › blob › master › lib › x32 › win32com › client › gencache.py
Pywin32/lib/x32/win32com/client/gencache.py at master · SublimeText/Pywin32
# Our gencache is in a .zip file (and almost certainly readonly) # but no dicts file. That actually needn't be fatal for a frozen · # application. Assuming they call "EnsureModule" with the same · # typelib IDs they have been frozen with, that EnsureModule will ·
Author   SublimeText
🌐
GitHub
gist.github.com › rdapaz › 63590adb94a46039ca4a10994dff9dbe
Fix for module win32com.gen_py has no attribute 'CLSIDToPackageMap' · GitHub
import logging import re from pathlib import Path from shutil import rmtree from win32com import client, __gen_path__ try: word = client.gencache.EnsureDispatch("Word.Application") except AttributeError as e: # Sometimes we might have to clean the cache to open m_failing_cache = re.search(r"win32com\.gen_py\.([\w\-]+)", str(e)) if m_failing_cache: cache_folder_name = m_failing_cache.group(1) logging.warning(f"Cleaning cache for '{cache_folder_name}'") cache_folder = Path(__gen_path__).joinpath(cache_folder_name) rmtree(cache_folder) word = client.gencache.EnsureDispatch("Word.Application") else: raise
🌐
Narkive
python-win32.python.narkive.com › PETUxcwo › win32com-client-gencache-ensuremodule-works-but-win32com-client-dispatch-does-not-for-a-certain
[python-win32] win32com.client.gencache.EnsureModule works but win32com.client.Dispatch does not for a certain TypeLib
October 1, 2018 - # Use these commands in Python code to auto generate .py support from win32com.client import gencache gencache.EnsureModule('{470874B8-3526-4DDB-BB88-7A8D7E968E3E}', 0, 1, 0)
🌐
UFPE
cin.ufpe.br › ~cfms › graduacao › 2007-2 › Projeto_Desenvolvimento › Software-PC › python › Lib › site-packages › win32com › client › gencache.py
https://www.cin.ufpe.br/~cfms/graduacao/2007-2/Pro...
Called once explicitly at module import below. try: _LoadDicts() except IOError: Rebuild() pickleVersion = 1 def _SaveDicts(): if is_readonly: raise RuntimeError, "Trying to write to a readonly gencache ('%s')!" \ % win32com.__gen_path__ import cPickle f = open(os.path.join(GetGeneratePath(), "dicts.dat"), "wb") try: p = cPickle.Pickler(f) p.dump(pickleVersion) p.dump(clsidToTypelib) finally: f.close() def _LoadDicts(): import cPickle # Load the dictionary from a .zip file if that is where we live.
🌐
Practical Business Python
pbpython.com › windows-com.html
Automating Windows Applications Using COM - Practical Business Python
July 2, 2018 - import win32com.client as win32 import pandas as pd from pathlib import Path # Read in the remote data file df = pd.read_csv("https://github.com/chris1610/pbpython/blob/master/data/sample-sales-tax.csv?raw=True") # Define the full path for the output file out_file = Path.cwd() / "tax_summary.xlsx" # Do some summary calcs # In the real world, this would likely be much more involved df_summary = df.groupby('category')['ext price', 'Tax amount'].sum() # Save the file as Excel df_summary.to_excel(out_file) # Open up Excel and make it visible excel = win32.gencache.EnsureDispatch('Excel.Application') excel.Visible = True # Open up the file excel.Workbooks.Open(out_file) # Wait before closing it _ = input("Press enter to close Excel") excel.Application.Quit()
🌐
Narkive
pyinstaller.narkive.com › O8Zsceb6 › import-problem-with-win32client-gencache-and-ensuredispatch
Import problem with win32client gencache and EnsureDispatch()
The rules of COM are that is should fall back to an older version so I should be able to specify the latest and get any older. PowerPoint has broken that by using a completely new CLSID not just the version number at the end (x0x5x0). BTW I noticed a fix for this on the py2exe wiki that simply sets gencache.readonly = false casing dispatch to create the fields as discussed above.
🌐
Python
mail.python.org › pipermail › python-win32 › 2013-March › 012751.html
[python-win32] win32com.client.gencache.EnsureModule works but win32com.client.Dispatch does not for a certain TypeLib
March 27, 2013 - I do the following: Run makepy.py with the -i argument and I pick EP_XmlProject 1.0 Type Library which shows the following: {470874B8-3526-4DDB-BB88-7A8D7E968E3E}, lcid=0, major=1, minor=0 >>> # Use these commands in Python code to auto generate .py support >>> from win32com.client import gencache >>> gencache.EnsureModule('{470874B8-3526-4DDB-BB88-7A8D7E968E3E}', 0, 1, 0) In PythonWin: >>> import win32com.client as wc >>> mod = wc.gencache.EnsureModule('{470874B8-3526-4DDB-BB88-7A8D7E968E3E}', 0, 1, 0) >>> print mod <module 'win32com.gen_py.470874B8-3526-4DDB-BB88-7A8D7E968E3Ex0x1x0' from 'C:\Python27\lib\site-packages\win32com\gen_py\470874B8-3526-4DDB-BB88-7A8D7E968E3Ex0x1x0.py'> this means that the module is created.
🌐
SourceForge
pyxr.sourceforge.net › PyXR › c › python24 › lib › site-packages › win32com › client › gencache.py.html
File- c:\python24\lib\site-packages\win32com\client\gencache.py
0053 try: 0054 _LoadDicts() 0055 except IOError: 0056 Rebuild() 0057 0058 pickleVersion = 1 0059 def _SaveDicts(): 0060 if is_readonly: 0061 raise RuntimeError, "Trying to write to a readonly gencache ('%s')!" \ 0062 % win32com.__gen_path__ 0063 import cPickle 0064 f = open(os.path.join(GetGeneratePath(), "dicts.dat"), "wb") 0065 try: 0066 p = cPickle.Pickler(f) 0067 p.dump(pickleVersion) 0068 p.dump(clsidToTypelib) 0069 finally: 0070 f.close() 0071 0072 def _LoadDicts(): 0073 import cPickle 0074 # Load the dictionary from a .zip file if that is where we live.
🌐
CSDN
devpress.csdn.net › python › 62fdac3d7e66823466192cf1.html
win32.Dispatch vs win32.gencache in Python. What are the pros and cons?_python_Mangs-Python
August 18, 2022 - To force the MakePy process, the win32com.client.gencache module is used. This module contains the code that manages the directory of MakePy-generated source files: the generated cache, or gencache.