Nevertheless this chapter is a nice starting point to explore the different parts that make up Pyro.
bin/* - Command-line tools__init__.py - Pyro package initializationconfiguration.py - Configuration codeconstants.py - Global constants used troughout Pyrocore.py - Core codenaming.py - Name Serverprotocol.py - Protocol adaptersutil.py - Utility codeerrors.py - Exception definitionsPyro.EventService - Event Server packagePyro.ext - Extensions packageYour code doesn't call a Pyro object directly. It calls a method on a proxy that acts just like the Pyro object it
represents. The proxy intercepts the method call by using a special implementation of __getattr__, that
passes the call to _invokePYRO. In turn, that method forwards the call to the protocol adapter, that
creates a message containing all the details of the call (using pickle to marshall all Python objects).
The message is passed via the network to the Pyro daemon on the other side.
The daemon receives the message and unmarshalls the request. It now knows the objectID of the required Pyro
objects, the desired member function to call, and its arguments. It looks up the Pyro Object in its table and calls
the Pyro_dyncall method. This method is in ObjBase which is the base class of all Pyro
objects. This method uses the appropriate apply call on itself to call the actual method. The result of
the method is handed back to the Pyro daemon, that marshalls it, and passes it back over the network to the calling
protocol adapter. The adapter on the client side unmarshalls the result data, hands it back to the proxy that called
it, and then the _invokePYRO method of the proxy returns the result data as if it was obtained using a
regular method call on a local object!
This was Pyro in a nutshell. There are many more things to consider, such as transporting modules (mobile objects or even mobile agents) and oneway calls, but you have to read the source anyway to find all the gory details.
| Tool | Implemented in | Notes |
|---|---|---|
| pyro-es | Pyro.EventService.Server | start Event Server |
| pyro-nsc | Pyro.nsc | control Name Server |
| pyro-xnsc | Pyro.xnsc | Tkinter-GUI version of nsc |
| pyro-wxnsc | Pyro.wxnsc | WxPython/WxWindows version of nsc, with nice tree view of namespace |
| pyro-genguid | Pyro.util | create a GUID, entrypoint is genguid_scripthelper() |
| pyro-ns / pyro-rns | Pyro.naming | start Name Server, entrypoint is main() |
| pyro-nsd / pyro-esd | Pyro.ext.daemonizer | Unix initd daemon scripts for name server and event server |
| pyro-nssvc / pyro-essvc | Pyro.ext.NS_NtService and ES_NTService | Windows NT Service control scripts for NS and ES |
__init__.py. It loads the configuration settings for
Pyro (Pyro.config.* items). This way, whenever a module from the Pyro package is imported, it can use
the config items right away.
Within the core package is also another package; Pyro.EventService. The event service is implemented
here: the Event Server itself and the base classes for event publishers and listeners.
Config class and a ConfigReader class. The
Config class is the container for all configuration items. The instance is available as
Pyro.config (created in the package initializer, see above). The configuration items are all attributes
of this object. Config uses the ConfigReader to read Pyro's configuration file. It deals
with defaults and environment settings too.
protocol module contains this. What the core module does
contain is all stuff that realize the core functions of Pyro:
ObjBasePyro_dyncall) and remote attribute access
(remote_getattr etc.)PyroURIPyroURI can be converted to and from a -
human readable - string.DynamicProxy and DynamicProxyWithAttrs_invokePYRO method
that intercepts method calls to pass them via the protocol adapter to the remote Pyro object.
Special care is taken to make proxy objects suitable for pickling so they can be transported
trough the Pyro protocol across the network.getProxyForURI and getAttrProxyForURIDaemonTCPServer and contains the server end of a protocol adapter. The daemon passes incoming method
calls (via its handleRequest method) to the protocol adapter that sorts out what to do exactly. The
connect and disconnect methods are used to keep track of server side Pyro objects. The
Daemon's handleError is used in case of a Pyro error, it processes the error and cleans things
up.initClient and initServer functions perform necessary initialization. For
instance, the server init code first checks the availability of the PYRO_STORAGE directory.NameServerLocatorgetNS method and you get a Pyro Proxy for the Name Server back.NameServerProxyNameServerLocator.getNS.NameServer and PersistentNameServerns script that starts the Name Server.NameValue and a NamedTree recursive data structure.BroadcastServerLoggerBaseSystemLoggerPyro.util.Log and this is Pyro's system logger
that writes to Pyro's system logfile.UserLoggerArgParsergetopt function in ANSI C. Pyro's command line
tools use this. It can parse command line options according to an option specification string. The
getOpt member is used to read the results.getGUIDgenguid_scripthelpergenguid command line utility, which prints a new GUID.getPyroTracebackPyro.PyroError and its derived exceptions. PyroError is the Pyro exception type that is
used for problems within Pyro. User code should not use it! Also, this module defines the
PyroExceptionCapsule class, which is used to represent any Python exception that has to be transported
across the network, and raised on the other side (by invoking raiseEx on this object).
Pyro/EventService/Clients.pySubscriber and Publisher base classes defined that you can use to easily
build publisher or listener clients for the ES.Pyro/EventService/Server.pyEventService Pyro object that is started by some utility code. This module is
called by the es script that you can use to start the Event Server.Pyro/ext/remote.pyPyro/ext/remote_nons.pyPyro/ext/daemonizer.pyPyro/ext/BasicNTService.pyPyro/ext/NS_NtService.pyPyro/ext/ES_NtService.pyPyro/ext/ServiceTest.py