Exemple 8
HOST = '127.0.0.1'
PORT = 8080
try:
from Tkinter import *
except ImportError:
from tkinter import *
try:
import tkColorChooser
except ImportError:
import tkinter.colorchooser as tkColorChooser
try:
import thread
except ImportError:
import _thread as thread
import socket
import pickle
import time
import sys
################################################################################
class ZSP:
'ZSP(socket) -> ZSP'
def __init__(self, socket):
'Initialize the Zero SPOTS Protocol object.'
self.__o_file = socket.makefile('bw', 0)
self.__i_file = socket.makefile('br', 0)
def send(self, obj):
'Send one object.'
pickle.dump(obj, self.__o_file, pickle.HIGHEST_PROTOCOL)
def recv(self):
'Receive one object.'
return pickle.load(self.__i_file)
################################################################################
class QRP:
'QRP(ZSP) -> QRP'
def __init__(self, ZSP):
'Initialize the Query/Reply Protocol object.'
self.__ZSP = ZSP
self.__error = None
self.__Q_anchor = []
self.__Q_packet = []
self.__R_anchor = {}
self.__Q_lock = thread.allocate_lock()
self.__R_lock = thread.allocate_lock()
thread.start_new_thread(self.__thread,())
def send_Q(self, ID, obj):
'Send one query.'
if self.__error:
raise self.__error
self.__ZSP.send((False, ID, obj))
def recv_Q(self, timeout=None):
'Receive one query.'
if self.__error:
raise self.__error
if timeout is not None:
if not isinstance(timeout, (float, int)):
raise TypeError('timeout must be of type float or int')
if not timeout >= 0:
raise ValueError('timeout must be greater than or equal to 0')
self.__Q_lock.acquire()
try:
try:
if self.__Q_packet:
Q = True
ID, obj = self.__Q_packet.pop()
else:
Q = False
anchor = [thread.allocate_lock()]
anchor[0].acquire()
self.__Q_anchor.append(anchor)
finally:
self.__Q_lock.release()
except AttributeError:
raise self.__error
if Q:
return ID, obj
if timeout:
thread.start_new_thread(self.__Q_thread, (timeout, anchor))
anchor[0].acquire()
try:
Q = anchor[1]
except IndexError:
if self.__error:
raise self.__error
raise Warning
return Q
def send_R(self, ID, obj):
'Send one reply.'
if self.__error:
raise self.__error
self.__ZSP.send((True, ID, obj))
def recv_R(self, ID, timeout=None):
'Receive one reply.'
if self.__error:
raise self.__error
if timeout is not None:
if not isinstance(timeout, (float, int)):
raise TypeError('timeout must be of type float or int')
if not timeout >= 0:
raise ValueError('timeout must be greater than or equal to 0')
anchor = [thread.allocate_lock()]
anchor[0].acquire()
self.__R_lock.acquire()
try:
try:
self.__R_anchor[ID] = anchor
finally:
self.__R_lock.release()
except AttributeError:
raise self.__error
if timeout:
thread.start_new_thread(self.__R_thread, (timeout, ID))
anchor[0].acquire()
try:
R = anchor[1]
except IndexError:
if self.__error:
raise self.__error
raise Warning
return R
def __thread(self):
'Private class method.'
try:
while True:
R, ID, obj = self.__ZSP.recv()
if R:
self.__R_lock.acquire()
if self.__R_anchor:
self.__R_anchor[ID].append(obj)
self.__R_anchor[ID][0].release()
del self.__R_anchor[ID]
self.__R_lock.release()
else:
self.__Q_lock.acquire()
if self.__Q_anchor:
anchor = self.__Q_anchor.pop()
anchor.append((ID, obj))
anchor[0].release()
else:
self.__Q_packet.append((ID, obj))
self.__Q_lock.release()
except Exception:
error = sys.exc_info()[1]
if isinstance(error, EOFError):
self.__error = EOFError
else:
self.__error = IOError
self.__Q_lock.acquire()
for anchor in self.__Q_anchor:
anchor[0].release()
del self.__Q_anchor
del self.__Q_packet
self.__Q_lock.release()
self.__R_lock.acquire()
for key in self.__R_anchor:
self.__R_anchor[key][0].release()
del self.__R_anchor
self.__R_lock.release()
def __Q_thread(self, timeout, anchor):
'Private class method.'
time.sleep(timeout)
self.__Q_lock.acquire()
if not self.__error and anchor in self.__Q_anchor:
anchor[0].release()
self.__Q_anchor.remove(anchor)
self.__Q_lock.release()
def __R_thread(self, timeout, ID):
'Private class method.'
time.sleep(timeout)
self.__R_lock.acquire()
if not self.__error and ID in self.__R_anchor:
self.__R_anchor[ID][0].release()
del self.__R_anchor[ID]
self.__R_lock.release()
################################################################################
class QRI:
'QRI(QRP) -> QRI'
def __init__(self, QRP):
'Initialize the Query/Reply Interface object.'
self.__QRP = QRP
self.__ID = 0
self.__lock = thread.allocate_lock()
def call(self, obj, timeout=None):
'Send one query and receive one reply.'
self.__lock.acquire()
ID = ''.join(chr(self.__ID >> shift & 0xFF) for shift in range(24, -8, -8))
self.__ID = (self.__ID + 1) % (2 ** 32)
self.__lock.release()
self.__QRP.send_Q(ID, obj)
return self.__QRP.recv_R(ID, timeout)
def query(self, timeout=None):
'Receive one query.'
return self.__QRP.recv_Q(timeout)
def reply(self, ID, obj):
'Send one reply.'
self.__QRP.send_R(ID, obj)
################################################################################
def qri(socket):
'Construct a QRI object.'
return QRI(QRP(ZSP(socket)))
################################################################################
def main():
global hold, fill, draw, look
hold = []
fill = '#000000'
connect()
root = Tk()
root.title('Paint 1.0')
root.resizable(False, False)
upper = LabelFrame(root, text='Your Canvas')
lower = LabelFrame(root, text='Their Canvas')
draw = Canvas(upper, bg='#ffffff', width=400, height=300, highlightthickness=0)
look = Canvas(lower, bg='#ffffff', width=400, height=300, highlightthickness=0)
cursor = Button(upper, text='Cursor Color', command=change_cursor)
canvas = Button(upper, text='Canvas Color', command=change_canvas)
draw.bind('<Motion>', motion)
draw.bind('<ButtonPress-1>', press)
draw.bind('<ButtonRelease-1>', release)
draw.bind('<Button-3>', delete)
upper.grid(padx=5, pady=5)
lower.grid(padx=5, pady=5)
draw.grid(row=0, column=0, padx=5, pady=5, columnspan=2)
look.grid(padx=5, pady=5)
cursor.grid(row=1, column=0, padx=5, pady=5, sticky=EW)
canvas.grid(row=1, column=1, padx=5, pady=5, sticky=EW)
root.mainloop()
################################################################################
def connect():
try:
start_client()
except:
start_server()
thread.start_new_thread(processor,())
def start_client():
global QRI
server = socket.socket()
server.connect((HOST, PORT))
QRI = qri(server)
def start_server():
global QRI
server = socket.socket()
server.bind(('', PORT))
server.listen(1)
QRI = qri(server.accept()[0])
def processor():
while True:
ID, (func, args, kwargs) = QRI.query()
getattr(look, func)(*args, **kwargs)
def call(func, *args, **kwargs):
try:
QRI.call((func, args, kwargs), 0.05)
except:
pass
################################################################################
def change_cursor():
global fill
color = tkColorChooser.askcolor(color=fill)[1]
if color is not None:
fill = color
def change_canvas():
color = tkColorChooser.askcolor(color=draw['bg'])[1]
if color is not None:
draw['bg'] = color
draw.config(bg=color)
call('config', bg=color)
################################################################################
def motion(event):
if hold:
hold.extend([event.x, event.y])
event.widget.create_line(hold[-4:], fill=fill, tag='TEMP')
call('create_line', hold[-4:], fill=fill, tag='TEMP')
def press(event):
global hold
hold = [event.x, event.y]
def release(event):
global hold
if len(hold) > 2:
event.widget.delete('TEMP')
event.widget.create_line(hold, fill=fill, smooth=True)
call('delete', 'TEMP')
call('create_line', hold, fill=fill, smooth=True)
hold = []
def delete(event):
event.widget.delete(ALL)
call('delete', ALL)
################################################################################
if __name__ == '__main__':
main()
Non, IMNSHO, une bonne question pour le format SO. Demander des ressources externes sur le multi-threading en python serait mieux. Et les répondants seraient mieux d'utiliser un blog ou un wiki quelque part. – dmckee
CPython est multi-threadé mais pas simultané, aucun des exemples ci-dessous que __don't__ utilise le module multi-traitement accélérera votre processus de plusieurs heures, il le ralentira dans la plupart des cas à cause du changement de contexte. voir http://en.wikipedia.org/wiki/Amdahl%27s_law –
Apparemment, personne n'aime beaucoup d'exemples. :-) Les commentaires sont appréciés! –