One path to connecting a Python script to a COM application on Windows
Tags: python, windows, windowscom
Published: 2024-04-19 18:42:05

**Background**
I am an experienced software engineer having developed mostly embedded and distributed applications.  Most of the experience gained during my system design and development years were with embedded systems or Linux.  I have never developed anything for Windows.

**Situation**
I decided to develop a Python application that could connect to a COM application.  Why?
1. I like Python because of the language’s flexibility and its vast community of solid contributions that allow us to not re-invent the wheel.
2. Many compelling applications are Windows-based and, while this is changing, many are not available for other platforms.

That kicked off my interesting journey during which the best discoveries were about awesome people who freely contribute and give their time and expertise with kindness and nurture.  Especially in communities like WinPython where, for example, Mark Hammond is exemplary https://www.oreilly.com/pub/au/59 & https://github.com/mhammond.  This write up is in homage to them and their efforts. 

**Setting**
- I have a Windows 11 Pro license – I am a beginner-to-intermediate level user of Windows because I have used a Mac for over 20 years.
- I know nothing about developing on Windows: the logistics, the practice, the constructs, anything really.
- I hate to mess with the base OS, so I always prefer self-contained environments that do not alter any OS settings.  Hence my intense dislike for anything to do with, for example, editing the Windows Registry.

**Objective**
Develop a Python application that can communicate with a COM application.

**STEP 1: Python on Windows**
**_What to install_**
Download and install WinPython from https://winpython.github.io. I researched Python on Windows and in very short order understood that WinPython is the way to go.  While it’s stated audience is scientists, data scientists and education, it fully serves the needs of personal projects. Also, it is available as a portable distribution with no requirement to register with Windows. This checked all the boxes.

**_How to install_**
- Download 7-zip
- Download WinPython to the Downloads / your folder of choice
- Extract WinPython

Assuming the distro was extracted to Downloads, use File Explorer to navigate to:
`C:\Users\<username>\Downloads\WPy64-31220\`

Double-click to launch WinPython Command Prompt

This brings up a command prompt shell with all the right environment variables set.

**_How to run Python_**
At this command prompt you can run the Python interpreter using:
`C:\Users\<username>\Downloads\WPy64-31220\python-3.12.2.amd64\python.exe`

Note: the inner folder will be named per your processor architecture.

Change directory to the “scripts” folder for the next few steps
`cd C:\Users\<username>\Downloads\WPy64-31220\scripts`

**_Make sure pip is installed and updated_**
`upgrade_pip.bat
pip install --upgrade pip`

**_Install the pywin32 package (and any others you want)_**
`pip install --upgrade pywin32`

At this point you are setup with Python and the required lower-level pywin32 package.

**STEP 2: Creating Python classes to interface with the target COM application**
The next step deals with the fact that while WinPython and other modules may understand the COM data structures for widely deployed applications, e.g. Excel, they won’t understand the COM data structures for your target COM application.  And they need to model those data structures as Python classes.  So, your next step is to generate these Python classes. (Note: the preceding description is likely not entirely accurate but my intent is to describe the gist of the need.)

Change directory:
`cd C:\Users\<username>\Downloads\WPy64-31220\python-3.12.2.amd64\Lib\site-packages\win32com\client`

**_Generate the required COM classes by running makepy_**
`C:\Users\<username>\Downloads\WPy64-31220\python-3.12.2.amd64\python.exe makepy.py`

This will pop up a Window that allows you to select the target registered program.  Select your program and click OK.

**_Confirm the required COM classes have been successfully generated by running combrowse_**
`C:\Users\<username>\Downloads\WPy64-31220\python-3.12.2.amd64\python.exe combrowse.py`

This will pop up a browser that you can navigate to confirm the target classes have been generated.

**STEP 3: Connecting to the target COM application in your Python script**
`import win32, win32com.client, pythoncom
myCOMAppHandle = win32com.client.DispatchEx (<name of COM App specified as a string>);`


**STEP 4: Calling the COM application**
NOTE: The code below is likely specific to my target COM, application – your application interface may differ
`z = win32com.client.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_R8, -6.2);
funcReturnCode = myCOMAppHandle.someAttr.someMethod(x, y, z)`
where x, y are input parameters, funcReturnCode is the code returned by the target COM application, and z is a return variable for data returned by the call.

That's it!