<previous | top | next> Pyro Manual

7. Example

(Note: this example is from Pyro 0.7 on Linux)
  1. Write a module 'test' containing a class 'testclass', which will be accessed remotely.
    from Pyro.errors import PyroException
    class testclass:
        def mul(s, arg1, arg2): return arg1*arg2
        def add(s, arg1, arg2): return arg1+arg2
        def sub(s, arg1, arg2): return arg1-arg2
        def div(s, arg1, arg2): return arg1/arg2
        def error(s): raise PyroException(ValueError('Server generated exception, this is ok!'))
  2. Using PyroC, generate client proxy code for 'testclass'. You can skip this part if you use the Dynamic Proxy in step 5.
    irmen@atlantis:~/Pyro/test > pyroc test
    Python Remote Object Compiler (c) Irmen de Jong. Pyro V0.7
    
    [added current directory to import path]
    processing module 'test' (/home/irmen/Pyro-0_7/test/test.py)...
    examining class PyroException ...
    imported from another module. Skipped.
    examining class testclass ...
    Generating proxy for testclass
    This release of Pyro doesn't need server-side skeleton code.
    
    All done. Output can be found in test_proxy.py .
  3. Write a server, testserver.py, that creates one or more instances of the 'testclass', and registers them with the Pyro Naming Service.
    import sys, socket
    import Pyro.naming
    import Pyro.core
    from Pyro.errors import PyroError
    
    import test
    
    ######## testclass object
    
    class testclass(Pyro.core.ObjBase, test.testclass):
    	pass
    
    ######## main program
    
    def main():
    	Pyro.core.initServer()
    	PyroDaemon = Pyro.core.Daemon()
    	locator = Pyro.naming.NameServerLocator()
    	print 'searching for Naming Service...'
    	try:
    		ns = locator.getNS()
    	except (PyroError,socket.error),x:
    		hn = socket.gethostname()
    		print '\nNaming Service not found with broadcast. Trying host',hn,'...',
    		ns = locator.getNS(host=hn)
    
    	print 'Naming Service found at',ns.URI.host,ns.URI.port
    
    	PyroDaemon.useNameServer(ns)
    
    	# connect a new object implementation:
    	PyroDaemon.connect(testclass(),'test')
    
    	print 'Ready.'
    	while 1:
    		PyroDaemon.handleRequests(3.0)
    		print '.',
    		sys.stdout.flush()
    
    if __name__=='__main__':
    	main()
  4. Write a client, testclient.py, that will find the Naming Service, then query the NS for the location of the object.
    import sys, socket
    import Pyro.naming, Pyro.core
    
    try:
    	import test_proxy
    	print '*** Using static test_proxy.'
    	dynproxy = 0
    except ImportError:
    	print '*** WARNING: no test_proxy found. Using dynamic proxy.'
    	dynproxy = 1
    
    
    Pyro.core.initClient()
    
    locator = Pyro.naming.NameServerLocator()
    print 'Searching Naming Service...',
    try:
    	ns = locator.getNS()
    except (Pyro.core.PyroError,socket.error),x:
    	import socket
    	hn = socket.gethostname()
    	print '\nNaming Service not found with broadcast. Trying host',hn,'...',
    	ns = locator.getNS(host=hn)
    
    print 'Naming Service found at',ns.URI.host,ns.URI.port
    
    print 'binding to object'
    try:
        URI=ns.resolve('test')
        print 'URI:',URI
    except Pyro.core.PyroError,x:
        print 'Couldn\'t bind object, nameserver says:',x
        raise SystemExit
     ... 
  5. Let the client create a proxy for the remote object by creating a 'test_proxy.testclass' instance for the given URI, or creating a Dynamic Proxy for the URI. Because the proxy appears the same as the real 'testclass', the client can now invoke methods on the remote objects.
     ...
    if dynproxy:
    	# use dynamic proxy
    	test = Pyro.core.getProxyForURI(URI)
    else:
    	# use static (precompiled) proxy
    	test = test_proxy.testclass(URI)
        
    print test.mul(111,9)
    print test.add(100,222)
    print test.sub(222,100)
    print test.div(2.0,9.0)
    print test.mul('*',10)
    print test.add('String1','String2')
    print '*** Now a server-generated exception should occur:'
    print test.error()
  6. Run the application in the network. First, start the Naming Service on one computer.
    irmen@atlantis:~/Pyro/test > ns
    Pyro Server Initialized. Using Pyro V0.7
    URI written to: /home/irmen/Pyro-0_7/bin/Pyro_NS_URI
    URI is: PYRO://atlantis:9090/c0a800639607-7f1594c35c0a7c4c-4a7e8648
    Naming Service started.
  7. Start the server on another computer (or in a different shell).
    irmen@atlantis:~/Pyro/test > python testserver.py 
    Pyro Server Initialized. Using Pyro V0.7
    searching for Naming Service...
    Naming Service found at atlantis 9090
    Ready.
    . . . . 
  8. Finally, run the client on a third computer (or in a different shell).
    irmen@atlantis:~/Pyro/test > python testclient.py
    *** Using static test_proxy.
    Pyro Client Initialized. Using Pyro V0.7
    Searching Naming Service... Naming Service found at atlantis 9090
    binding to object
    URI: PYRO://atlantis/c0a800633d2e-7f15d1dc5c0a843d-796a387e
    999
    322
    122
    0.222222222222
    **********
    String1String2
    *** Now a server-generated exception should occur:
    Traceback (innermost last):
      File "testclient.py", line 51, in ?
        print test.error()
      File "test_proxy.py", line 26, in error
        return S.adapter.remoteInvocation('error',0)
      File "/home/irmen/Pyro/Pyro/protocol.py", line 59, in remoteInvocation
        answer.raiseEx()
      File "/home/irmen/Pyro/Pyro/errors.py", line 52, in raiseEx
        raise self.excObj
    ValueError: Server generated exception, this is ok!
  9. You might want to peek in the Naming Server:
    irmen@atlantis:~/Pyro/test > nsc list
    Finding NS using broadcast @ port 9091
    LOCATOR: Searching Pyro Naming Service...
    NS is at atlantis port 9090
    -------------- START DATABASE
    Pyro.NameServer  -->  PYRO://atlantis:9090/c0a800639607-7f1594c35c0a7c4c-4a7e8648
    test  -->  PYRO://atlantis/c0a800633d2e-7f15d1dc5c0a843d-796a387e
    -------------- END
  10. And if you're interested you may want to try the logging facility of Pyro. First, set the tracelevel to something other than the default, 0. See the chapter on configuration how to do that. Usually you'll set the environment variable PYRO_TRACELEVEL to 3 (=maximum logging). Then, when you start Pyro programs (like the nameserver), they will write something like this to the logfile:
    ------------------------------------------------------------ NEW SESSION
    Thu Dec  9 12:42:16 1999   Pyro Initializing, version 0.7
    This is initServer.
    Configuration settings are as follows:
    PYRO_BC_RETRIES = 2
    PYRO_BC_TIMEOUT = 2
    PYRO_BINARY_PICKLE = 1
    PYRO_LOGFILE = /home/irmen/Pyro-0_7/test/Pyro_log
    PYRO_NS_BC_PORT = 9091
    PYRO_NS_NAME = Pyro.NameServer
    PYRO_NS_PORT = 9090
    PYRO_PORT = 7766
    PYRO_STORAGE = /home/irmen/Pyro-0_7/test
    PYRO_TRACELEVEL = 3
    Init done.
    ----------------------------------------------------------------------
    12/09/99 12:42:16 ** NOTE ** PYROAdapter ** adapter daemon set to <Pyro Daemon on atlantis:9090>
    12/09/99 12:42:16 ** NOTE ** NameServer ** registered Pyro.NameServer with URI PYRO://atlantis:9090/c0a8006380b6-7f166fe323bb032f-6f30696a
    12/09/99 12:42:16 ** NOTE ** NS daemon ** This is Pyro Naming Service V0.7.
    12/09/99 12:42:16 ** NOTE ** NS daemon ** Starting on atlantis port 9090 ('192.168.0.99', 9090) , broadcast server on port 9091