How to make friends python with win32 api

Embed Size (px)

Citation preview

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 conversionFlow (events, async methods) handlingMultithreading supportExtensibility

Envisioned solution

Or...

What Ive found

pywin32 package on sourceforge.net by Mark Hammondpython interpreter builds: ActiveState, Anaconda, Canopy with pywin32Python Programming On Win32 by Mark Hammond and Andy Robinsonno actual documentation on activestate.com

Pywin32 workflow

Make Handle Events classMake client object with DispatchWithEvents methodUse 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_pyRun '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 conversionFlow (events, async methods) handling

Issues:

Multithreading supportExtensibilityNot stable (?)

Manager

Workflow

Add event queueCreate custom ManagerMake 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

" " " workflow" - - 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()

Solution
v. 0.2

Contacts

Linkedin: https://linkedin.com/in/eugene-lopatkinE-mail: [email protected]

Thank you! Any questions?