How to make friends of
Python and Win32 API
Connecting the Python to a Win32 API
provided by a stock broker
What was expected
Terms
Real world
?
Issues
COM to pure Python object conversion
Flow (events, async methods) handling
Multithreading support
Extensibility
Envisioned solution
Or...
What I’ve found
pywin32 package on sourceforge.net by Mark Hammond
python interpreter builds: ActiveState, Anaconda, Canopy
with pywin32
Python Programming On Win32 by Mark Hammond and
Andy Robinson
no actual documentation on activestate.com
Pywin32 workflow
Make Handle
Events class
Make client object
with
DispatchWithEve
nts method
Use API
methods on
python
object
Python client structure
Event class
class ClientEvents:
def OnAddBar(self, row, nrows, symbol,
interval, datetime, open, high, low, close,
volume, open_int):
pass # some logic
…
Client
clnt =
client.DispatchWithEvents('COM.Server.1',
ClientEvents)
…
clnt.GetBars('SBER', bar_interval,
date_time_object, 10)
Cool tool
Make folder python_folderLibsite-
packageswin32comgen_py
Run 'win32comclientmakepy.py' (eg, run it from the
command window, or double-click on it) and a list will be
presented. Select the Type Library.
It will generate python wrapper classes from COM Library
with all available methods.
Convert DateTime objects
def pytime_2_datetime(pythime):
return dt(year=pythime.year,
month=pythime.month, day=pythime.day,
hour=pythime.hour, minute=pythime.minute,
second=pythime.second)
def datetime_2_pytime(datetime):
return pywintypes.Time(time
.mktime(datetime.timetuple()))
Solution v. 0.1
COM to pure Python
object conversion
Flow (events, async
methods) handling
Issues:
Multithreading support
Extensibility
Not stable (?)
Manager
Workflow
Add event
queue
Create custom
Manager
Make proxy to
COM Object
Get pure
python Events
queue
Use proxy and
queue from
other threads
Modify Event class, part 1
class ClientEvents:
def __init__(self):
self.event_queue = Manager().Queue()
def get_event_queue(self):
return self.event_queue
…
Modify Event class, part 2
class ClientEvents:
…
def OnAddBar(self, row, nrows, symbol,
interval, datetime, open, high, low, close,
volume, open_int):
self.event_queue.put_nowait(('AddBar',
row, nrows, symbol, interval,
pytime_2_datetime(datetime), open, high, low,
close, volume, open_int))
Use multiprocessing.Manager
class ComManager(BaseManager):
pass
Add client method
def get_com_server():
CoInitializeEx(COINIT_MULTITHREADED)
clnt =
client.DispatchWithEvents('COM.Server.1',
ClientEvents)
CoUninitialize()
return clnt
Register methods
ComManager.register('get_com_server',
callable=get_com_server,
exposed=('CancelBidAsks',
'CancelOrder',
'GetBars',
'GetMoneyAccount', …,
'get_event_queue'))
Fix DateTime bug, part 1
class ClientEvents:
def GetBarsSer(self, symbol, interval,
since, count):
self.GetBars(symbol, interval,
datetime_2_pytime(since), count)
Fix DateTime bug, part 2
ComManager.register('get_com_server',
callable=get_com_server,
exposed=('CancelBidAsks',
'CancelOrder',
'GetBars',
'GetMoneyAccount', …,
'get_event_queue',
'GetBarsSer'))
Connection server solution
Use as server, server code
if __name__ == '__main__':
freeze_support()
m = ComManager(address=('127.0.0.1', port,
authkey='authkey').get_server()
.serve_forever()
Use as server, client code
…
manager = ComManager(address='address', port,
authkey='authkey')
manager.connect()
com_server =manager.get_com_server()
com_event_queue =
com_server.get_event_queue()
Stand-alone
In code use
from package_mame import ComManager
if __name__ == '__main__':
freeze_support()
manager = ComManager()
manager.start()
com_server = manager.get_com_server()
com_event_queue =
com_server.get_event_queue()
Solution
v. 0.2
Contacts
Linkedin: https://linkedin.com/in/eugene-lopatkin
E-mail: eugenelopatkin@gmail.com
Thank you! Any questions?

How to make friends python with win32 api