1 # as you can see - the import line now requires even less typing!
\r
3 c = SocketConnection("localhost")
\r
5 #------------------------------------------------------------------------------
\r
6 # this demo shows the new `execute` and `namespace` features of rpyc
\r
7 #------------------------------------------------------------------------------
\r
10 # the code below will run AT THE OTHER SIDE OF THE CONNECTION... so you'll see
\r
11 # 'hello world' on the server's console
\r
12 c.execute("print 'hello world'")
\r
15 c.modules.sys.stdout = sys.stdout
\r
17 # and this time, on our console
\r
18 c.execute("print 'brave new world'")
\r
21 c.modules.sys.stdout = c.modules.sys.__stdout__
\r
23 # anyway, the `execute` method runs the given code at the other side of the connection
\r
24 # and works in the `namespace` dict. what?
\r
25 c.execute("x = [1,2,3]")
\r
28 # now it makes sense, doesn't it? the 'namespace' attribute is something i called
\r
29 # AttrFrontend -- it wraps a dict with the attribute protocol, so you can access
\r
30 # it with the dot notation, instead of the braces notation (more intuitive).
\r
31 # this namespace works both ways -- executing code affects the namespace, while
\r
32 # altering the namespace directly also affects it:
\r
33 c.namespace.x.append(4)
\r
34 c.execute("x.append(5)")
\r
37 # but you should not assign complex objects (not int/float/str, etc) to this namespace
\r
38 # directy, or NetProxies will be created. there's nothing wrong with that, but keep
\r
39 # in mind it might cause blocking (and even deadlocks), as i'll explain later.
\r
41 # another cool thing i want to show is the second, optional parameter to execute: mode.
\r
42 # the mode controls how the code is compiled. the default mode is "exec", which means
\r
43 # it executes the code as a module. the other option is "eval" which returns a value.
\r
44 # so if you want to _do_ something, like printing of assigning a variable, you do it
\r
45 # with "exec", and if you want to evaluate something, you do it with "eval"
\r
48 # this will print None
\r
49 print c.execute("1+2")
\r
51 # while this will print 3
\r
52 print c.execute("1+2", "eval")
\r
54 # but there's a time in a man's life when he asks himself, why the heck? you can, as i
\r
55 # showed in other places, just do this:
\r
56 # c.modules.__builtin__.eval("1+2")
\r
57 # so what's the point?
\r
59 # well, i've been waiting for this question. the rationale behind this seemingly useless
\r
60 # feature is for times you NEED to have the code executing remotely, but writing a
\r
61 # dedicated module for it is overdoing it:
\r
62 # * more files to update ==> more chance that you'll forget to update
\r
63 # * distributing the module to all of the machines
\r
64 # * making a mess on the file system
\r
65 # * it's really not a module... it's just some code that logically belongs to one single
\r
66 # module, but technical difficulties prevent it
\r
68 # and to show you what i mean -- i want to start a thread on the server, like it did in
\r
69 # several places over the demos. this thread will send me an event every second. what i
\r
70 # used to do was, creating another module, like testmodule.py to define the thread
\r
71 # function, so it will exist on the server, and i could call it.
\r
72 # if i defined thread_func at the client side, then the thread will block when trying
\r
73 # to execute the code, because the client holds it. so this new mechanism lets you
\r
74 # distribute code in a volatile fashion:
\r
75 # * when the connection is closed, everything you defined is gone
\r
76 # * no file-system mess
\r
77 # * no need to distribute files across the network
\r
78 # * only one place to maintain
\r
81 my_thread_active = True
\r
83 def my_thread_func(callback):
\r
85 from Rpyc import Async
\r
87 callback = Async(callback)
\r
88 while my_thread_active:
\r
89 callback(time.time())
\r
91 print "the thread says goodbye"
\r
94 def callback(timestamp):
\r
95 print "the timestamp is", timestamp
\r
97 c.modules.thread.start_new_thread(c.namespace.my_thread_func, (callback,))
\r
98 c.modules.time.sleep(5)
\r
99 c.namespace.my_thread_active = False
\r
102 # it's not only for threads of course. there are many times when you NEED the code/objects
\r
103 # on the remote side. for example:
\r
104 # * situations that would block (like having the thread func on the client)
\r
105 # * code that check the type of the object (type or isinstance), and a NetProxy would make
\r
106 # it cry. DONT CHECK THE TYPE OF OBJECTS, PEOPLE, JUST USE THEM! that's why they invented
\r
107 # duck-typing. argh.
\r
108 # * other places i didnt think of as of yet. i want to sleep. leave me alone ;) zzzZZZ
\r