Python-based Web Server. (Actually, it can be used for other TCP-IP servers also - NNTP, FTP, etc.) - As of Aug'2006, the web page was last updated Dec'2005, and the code last updated Sept'2003. There's almost no Email List discussion in 2005-2006. Is that a good thing or a bad thing? Medusa is different from most other servers because it runs as a single process, multiplexing I/O with its various client and server connections within a single process/thread. (ASynch)

  • vs.... Multi Threaded programs are notoriously difficult to write and debug - especially with servers that want to utilize persistent shared data - great care must be taken when accessing or modifying shared resources. This translates into larger and more complex code.

  • but you can't (easily) make connections to an external SQL database, process, or server where the queries might take on the order of seconds. To solve that problem, check out the EGroups Co Routine stuff.

used in Zope - it is a "synchronized" version of Medusa, a Python library for asynchronous high-performance multiprotocol server written by Sam Rushing. Zope can't handle a fraction of what Medusa manages because every request to an object is met with a thread. In Zope 1 and 2, only static content is served asynchronously.

used in Quixote

used in EGroups, though mostly for Intranet servers

initially done by Sam Rushing, taken over by Andrew Kuchling

running Medusa on my IBook


  • running from a documents subdirectory, not the python directory

    • so needed to do some path playing to feed sys.path.append() so the medusa module would be recognized/imported
  • now getting some error in starting up the monitoring daemon::

Traceback (most recent call last): File "", line 149, in ? ms = monitor.secure_monitor_server ('fnord', '', MONITOR_PORT) File "/Users/billseitz/Documents/flux/medusa/", line 262, in init monitor_server.init (self, hostname, port) File "/Users/billseitz/Documents/flux/medusa/", line 165, in init self.create_socket (socket.AF_INET, socket.SOCK_STREAM) File "/Library/Frameworks/Python.framework/Versions/2.4//lib/python2.4/", line 261, in create_socket self.add_channel() File "/Library/Frameworks/Python.framework/Versions/2.4//lib/python2.4/", line 244, in add_channel map = self._map File "/Library/Frameworks/Python.framework/Versions/2.4//lib/python2.4/", line 366, in getattr return getattr(self.socket, attr) Attribute Error: '_socketobject' object has no attribute '_map'

  • is this related to this ?

    • ah, this looks relevant

    • so add 'asyncore.dispatcher.init(self)' line to 'monitor.monitor_server.init'


  • now when start up get another trace::

Chat Server (V1.4) started on port 8888 Traceback (most recent call last): File "", line 194, in ? os.setegid (gid) O S Error: [Errno 1] Operation not permitted

  • apparently MacOs X returns"posix" but does not have os.setegid

  • just try putting that little block inside a 'try', with the except doing a 'pass'

  • now no error when launch

  • asking for http://localhost:8080/ gives error 404

    • ah, uses file root of '/home/www' - change that, added an 'index.html' file to the medusa demo directory
  • but how do I get it to deliver any dynamic/script output?

Sept 9

  • see 'demo/' which uses and seems to want script files to have an '.mpy extension.

  • quit and launch

  • make 'test.mpy' file which has no functions or anything else, just a static print line.

  • hit the URI in the browser, get the static output. Good.

  • tweak test.mpy to print 2*2; hit the URI, get back 4. Good.

  • tweak test.mpy to have a function which returns 2*2, and a main that prints the function. Hit URI, get empty page back. Try just calling 'python test.mpy' from command line, out pops '4', so no obvious stupid mistake there. And terminal window log says it's associating the call with responseCode=200 so that's a good sign.

    • also, code seems to work by just calling execfile(test.mpy) - no argument passing? Or do I just assume any arguments that have been passed in the HTTP request have been stuffed into a globals() that's available? I guess I'll deal with that later...


  • found a form and a script as examples.

    • note that the script does 'import cgi' to get access to params

      • but I saw another comment somewhere about someone not getting 'cgi.FieldStorage()' to work right
  • realized I didn't need to put my call in a name=main block - once I took it out of there, got my mpy to render a value

Edited:    |       |    Search Twitter for discussion