Posts Tagged ‘Python’
Buona nerdlettura.
Il linguaggio Python offre, fra le sue librerie standard, almeno due opzioni per realizzare la temporizzazione delle funzioni o detto altrimenti, per eseguire una funzione ad un certo orario o dopo un tot di secondi.
La libreria “sched” (http://www.python.org/doc/2.5.2/lib/module-sched.html) è la prima opzione ma non ci piace perché non consente di restituire il controllo al main durante l’attesa.
La seconda, focus di questo articolo, è la funzione Timer della libreria “threading” (http://docs.python.org/library/threading.html).
Osservando il codice di threading.py (che trovate ad esempio in /usr/lib/python2.6/):
[...]
def Timer(*args, **kwargs):
return _Timer(*args, **kwargs)
class _Timer(Thread):
"""Call a function after a specified number of seconds:
t = Timer(30.0, f, args=[], kwargs={})
t.start()
t.cancel() # stop the timer's action if it's still waiting
"""
def __init__(self, interval, function, args=[], kwargs={}):
Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.finished = Event()
def cancel(self):
"""Stop the timer if it hasn't finished yet"""
self.finished.set()
def run(self):
self.finished.wait(self.interval)
if not self.finished.isSet():
self.function(*self.args, **self.kwargs)
self.finished.set()
[...]
si nota che il costruttore prende in ingresso:
– interval: il numero di secondi dopo i quali eseguire la funzione
- function: il nome della funzione
- args: lista opzionale di argomenti della funzione
- kwargs: dizionario opzionale di argomenti con nome
Nel metodo run, si può infatti notare che la chiamata: self.function(*self.args, **self.kwargs) accetta una lista e/o un dizionario.
Per capire come utilizzarli si può far riferimento a questo articolo:
“the mysterious miss args and mister kwargs”
Vediamo ora alcuni esempi di utilizzo di un Timer.
import time
from threading import Timer
def print_time():
print "From print_time", time.time()
def print_some_times():
print "From print_some_times", time.time()
Timer(2, print_time).start()
print_some_times()
Dentro print_some_times() invochiamo print_time() che verrà eseguita tra 2 secondi.
import time
from threading import Timer
def print_time(arg):
print arg
print "From print_time", time.time()
def print_some_times():
a = ["my_arg"]
print "From print_some_times", time.time()
Timer(2, print_time, a).start()
print_some_times()
Stesso di sopra ma con un parametro passato alla funzione print_time().
Nota bene: il parametro – anche se singolo – deve essere passato come lista di elementi.
Il passaggio di più parametri può avvenire utilizzando:
def print_time(arg1, arg2, ..., argN)
con relativo:
a = ["my_arg1", "my_arg2", ..., "my_argN"]
oppure con la sintassi:
def print_time(*args)
e relativo:
a = ["my_arg1", "my_arg2", ..., "my_argN"]
Lo script diventa quindi:
import time
from threading import Timer
def print_time(*args):
print args
print "From print_time", time.time()
def print_some_times():
a = ["my_arg1", "my_arg2", "my_arg3", 1, 5, "ancora_stringa"]
print "From print_some_times", time.time()
Timer(2, print_time, a).start()
print_some_times()
e così via.
Lo stesso discorso vale per kwargs usando la sintassi:
b = {"name1":"value1", "name2":2, ...}
import time
from threading import Timer
def print_time(*args, **kwargs):
print args
print kwargs
print "From print_time", time.time()
def print_some_times():
a = ["quattro", "otto", "quindici", 16, 23]
b = {"name1":"jack", "name2":"kate", "name3":"sawyer", "number": 42}
print "From print_some_times", time.time()
Timer(2, print_time, a, b).start()
print_some_times()
Buona nerdpratica.
Il mio primo articolo si concentrerà sulla creazione di un semplice script in Python, avviabile solo con la diretta esecuzione (doppio click sul file .py), utile per cliccare ripetutamente su uno o più determinati punti dello schermo, sulle finestre, bottoni, banner, etc. Una particolarità di questo script è quella di “sentire” gli input provenienti dalla tastiera anche se la finestra non è “a fuoco” cioè anche se non è l’attuale finestra in primo piano e attiva.
In breve, vengono creati due thread che comunicano mediante un buffer condiviso (come nel classico problema produttore/consumatore):
- t_keyboard: si occupa di ascoltare gli eventi della tastiera (i tasti premuti). È il produttore e inserisce i caratteri letti nel buffer
- t_mouse: gestisce il mouse, catturandone la posizione, spostandolo e facendolo cliccare. Si tratta del consumatore.
Le librerie/moduli accessorie sono:
- PyWin32
- PyHook
- SendKeys
"""
Project Name:....Aut0 P0int & Click v1.0
Author:..........Mauro "Baba" Mascia
Date:............2009/02
Thanks to:
- Peter Parente
- "BlueKitties" for the article "Mouse/Keyboard control scripting module."
- prof. Matteo Pradella
"""
from ctypes import*
from SendKeys import*
from pyHook import *
from time import strftime
from time import sleep
from threading import Thread
from threading import Lock
import pythoncom
import sys
"""
Create a thread that handle the keyboard
All key pressed are stored in a shared buffer
"""
class t_keyboard(Thread):
def __init__(self, buff):
Thread.__init__(self)
self.buff = buff
def run(self):
def OnKeyboardEvent(event):
char = chr(event.Ascii)
if char in ['r', 'd', 'q']:
if not self.buff.put(char):
print "full buffer"
if event.Key == 'Escape':
sys.exit()
return True
hm = HookManager()
hm.KeyDown = OnKeyboardEvent
hm.HookKeyboard() # set the hook
# Wait forever and print keys
pythoncom.PumpMessages()
"""
Create a thread that handle the mouse
"""
class t_mouse(Thread):
def __init__(self, buff):
Thread.__init__(self)
self.buff = buff
def run(self):
class POINT(Structure):
_fields_ = [("x", c_ulong),("y", c_ulong)]
#Gets the current mouse position
def getpos():
global pt
pt = POINT()
windll.user32.GetCursorPos(byref(pt))
return pt.x, pt.y
#Calculate how many minutes are now
def minNow():
h_now = int(strftime("%H")) #hours
m_now = int(strftime("%M")) #mins
t_now = h_now * 60 + m_now #time in mins
return t_now
#Moves the cursor to x,y cordinate
def move(x,y):
windll.user32.SetCursorPos(x,y)
#Clicks in the actual mouse position
def click():
LEFTDOWN = 0x00000002
LEFTUP = 0x00000004
windll.user32.mouse_event(LEFTDOWN,0,0,0,0)
windll.user32.mouse_event(LEFTUP,0,0,0,0)
print "Punta e clicca fino alle:"
while True:
h_end = int(raw_input("ora:"))
if(h_end <= 24 and h_end > 0):
break
while True:
m_end = int(raw_input("min:"))
if(m_end <= 60 and m_end >= 0):
break
t_end = h_end*60+m_end
print "\n------\nPremi:\n"
print "- \'r\' per impostare le coordinare del mouse"
print "- \'d\' per cominciare la riproduzione"
print "- \'q\' per arrestare la riproduzione"
print "- Esc per uscire"
print "\n------\n"
coords = []
while True:
char = self.buff.get() #reads from buffer
if char == 'r':
x, y = getpos() #gets current position
print "Catturata coordinata X:%d,Y:%d" %(x,y)
coords.append((x, y))
elif char == 'd' and len(coords)>0:
print "Riproduzione..."
while minNow() < t_end:
for x,y in coords:
move(x,y)
click()
sleep(0.08)
if self.buff.get() == 'q':
print "stopped"
break
break
else:
"""
sleep for a while if char isnt "r" or "d"
this is foundamental to release CPU's resources
"""
sleep(0.001)
class Buffer(object):
def __init__(self, size) :
self.data = [None for x in xrange(size)]
self.size = size
self.head = self.tail = 0
self.the_lock = Lock()
def put(self, x):
self.the_lock.acquire()
if self.data[self.tail] != None :
self.the_lock.release()
return False # full
self.data[self.tail] = x
self.tail = (self.tail+1) % self.size
self.the_lock.release()
return True
def get(self) :
self.the_lock.acquire()
if self.data[self.head] == None :
self.the_lock.release()
return None # empty
v = self.data[self.head]
self.data[self.head] = None
self.head = (self.head+1) % self.size
self.the_lock.release()
return v
print "Aut0 P0int & Click v1.0\n"
buf = Buffer(100)
keyboard = t_keyboard(buf)
mouse = t_mouse(buf)
keyboard.start()
mouse.start()