1. Michael Forbes
  2. asyncplot

Commits

ksbuble  committed ba0b903

Autolaunch the Client process from the server.
server.py - Pickle the Plotter and pass it to the client cmd. Launch the client process by executing the client cmd with Popen.
client.py - add command line string that unpacks the plotter from the Server, creates the client object and runs it.
example1.py - define the Plotter object. Call plt.clf() in draw().

  • Participants
  • Parent commits b22b239
  • Branches default

Comments (0)

Files changed (4)

File README.rst

View file
  • Ignore whitespace
 * Comprehensive testing
 * Logging (print debug messages in debug mode for checking network problems)
 * Profile performance.
-* Auto-launch client.
+* Auto-launch client from the server.
 
-  * Ideally, the user can define the plotting code in a (picklable) class, and
-    then simply provide that class to the Server() constructor.  The class will
-    then spawn, or fork a new python interpreter, import a client, and run the
-    client.  (Right now the user needs to specify the entire command line
-    including the invocation of the interpreter and all imports.)
+  * The user defines the plotting code in a (picklable) class, and
+    provides the class to the Server() constructor.  The Server passes the pickled Plotter
+    to the client when the client process is launched in a new python interpreter. 
+    The python interpreter command line options for the client are passed to the Server 
+    constructor at the time of instantiation. Default values are: 
+    (ex. ["ipython", "--pylab=osx", "-c"])
 
 * Configuration (hostname, port specification etc.)
 

File asyncplot/client.py

View file
  • Ignore whitespace
 r"""Example computation Client."""
 import cPickle
-import time
 import socket
 
-import server
+_CLIENTCOMMAND = """
+import cPickle
+import client
+Plotter = cPickle.loads(%(Plotter)s)
+c = client.Client(Plotter=Plotter, host=%(host)s, port=%(port)i)
+c.run()
+"""
 
 
 class Client(object):
-    def __init__(self, Plot,
-                 host=server.PlotSocketServer._HOST,
-                 port=server.PlotSocketServer._PORT):
+
+    client_command = _CLIENTCOMMAND
+
+    def __init__(self, Plotter, host=None, port=None):
+        import server
+        if host is None:
+            host = server.PlotSocketServer._HOST
+        if port is None:
+            port = server.PlotSocketServer._PORT
         self.host = host
         self.port = port
-        self.plot = Plot()
-        self.plot.plt.clf()
+        self.plot = Plotter()
         self._BUF_SIZE = 2**12
 
     def get_data(self):

File asyncplot/example1.py

View file
  • Ignore whitespace
 def run():
     # Create a plot instance.  This should launch the plot process, and pop up
     # the initial plot window.
-    p = server.Server(Plotter=Plotter, wait_for_client=True)
-
-    # Start the computation
-    x = np.linspace(0, 2*np.pi, 10)
-    dt = 0.001
-    t = 0
-    for n in xrange(10000000):
-        if n % 100000 == 0:
-            print n
-        t += dt
-        y = np.sin(x - t)
-        p.update(x=x, y=y)
+    with server.Server(Plotter=Plotter, wait_for_client=True) as p:
+        # Start the computation
+        x = np.linspace(0, 2*np.pi, 10)
+        dt = 0.001
+        t = 0
+        for n in xrange(10000000):
+            if n % 100000 == 0:
+                print n
+            t += dt
+            y = np.sin(x - t)
+            p.update(x=x, y=y)
 
 
 def run_client():

File asyncplot/server.py

View file
  • Ignore whitespace
 import subprocess
 import threading
 import SocketServer
+import client
 
 import mmf
 
         self.lock = threading.Lock()  # RLock()??
         self.have_data = threading.Event()
         self.data = None
-        
         self.daemon_threads = True       # Don't keep python alive.
         self.allow_reuse_address = True  # Allow port reuse after termination.
         SocketServer.TCPServer.__init__(self, (host, port),
         self.have_data.wait()
         with self.lock:
             return cPickle.dumps(self.data)
-        
+
     def update(self, *v, **kw):
         with self.lock:
             self.data = (v, kw)
                  Plotter=None,
                  host=PlotSocketServer._HOST,
                  port=PlotSocketServer._PORT,
-                 client_cmd=None,
+                 client_cmd=["ipython", "--pylab=osx", "-c"],
                  wait_for_client=False):
         r"""
         Parameters
            If `True`, then pause server to allow the user to adjust plot
            windows.
         """
+        self.Plotter = Plotter
         self.client_cmd = client_cmd
         self.wait_for_client = wait_for_client
         self.server = PlotSocketServer(host=host, port=port)
         threading.Thread.__init__(self, target=self.server.serve_forever)
         self.daemon = True               # Don't keep python alive.
 
+    def _start_client(self):
+        client_process = None
+        if self.Plotter is not None:
+            host, port = self.server.server_address
+            client_code = client.Client.client_command % dict(
+                Plotter=repr(cPickle.dumps(self.Plotter)),
+                host=repr(host),
+                port=port)
+            client_cmd = self.client_cmd + [client_code]
+            client_process = subprocess.Popen(client_cmd,
+                                                   # I/O??????
+                                                   )
+            return client_process
+        
     def __enter__(self):
         self.start()
-        if self.client_cmd is not None:
-            self.client_process = subprocess.Popen(self.client_cmd,
-                                                   # I/O??????
-                                                   )
-        else:
-            self.client_process = None
-        
+        self.client_process = self._start_client()
         if self.wait_for_client:
             raw_input("Adjust plot windows and press return to continue...")