how to make friends python with win32 api
TRANSCRIPT
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 DispatchWithEvents 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_folder\Lib\site-packages\win32com\gen_py
Run 'win32com\client\makepy.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 ComManagerif __name__ == '__main__': freeze_support() manager = ComManager() manager.start() com_server = manager.get_com_server() com_event_queue = com_server.get_event_queue()
Solutionv. 0.2
Contacts
Linkedin: https://linkedin.com/in/eugene-lopatkin
E-mail: [email protected]
Thank you! Any questions?