#252 SqlObject fails in mod_python because of KeyError

closed-wont-fix
Oleg Broytman
General (125)
5
2009-06-26
2009-05-19
Anonymous
No

A simple python handler in apache which uses sqlobject fails because of a KeyError.

sqlobject/main.py in line 762:
mod = sys.modules[cls.__module__]

Uncommenting the lines makes sqlobject work as intended.

Attached is the test script and the debug output from the script when run as a mod_python handler.

I do not have the error when running test scripts in the console. I am guessing it must be something that mod_python is doing when importing sqlobject.

Discussion

  • test script used to trigger the error

     
    Attachments
  • damike
    damike
    2009-05-19

    Sorry about submitting to early - Here is the bug report:
    --------
    MOD_PYTHON ERROR

    ProcessId: 4361
    Interpreter: 'huge.dino.park'

    ServerName: 'huge.dino.park'
    DocumentRoot: '/var/www/'

    URI: '/~michael/test.py'
    Location: None
    Directory: '/home/michael/public_html/'
    Filename: '/home/michael/public_html/test.py'
    PathInfo: ''

    Phase: 'PythonHandler'
    Handler: 'mod_python.publisher'

    Traceback (most recent call last):

    File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1537, in HandlerDispatch
    default=default_handler, arg=req, silent=hlist.silent)

    File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1229, in _process_target
    result = _execute_target(config, req, object, arg)

    File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1128, in _execute_target
    result = object(arg)

    File "/usr/lib/python2.5/site-packages/mod_python/publisher.py", line 204, in handler
    module = page_cache[req]

    File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 1059, in __getitem__
    return import_module(req.filename)

    File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 296, in import_module
    log, import_path)

    File "/usr/lib/python2.5/site-packages/mod_python/importer.py", line 680, in import_module
    execfile(file, module.__dict__)

    File "/home/michael/public_html/test.py", line 7, in <module>
    class News(sqlobject.SQLObject):

    File "/usr/lib/python2.5/site-packages/sqlobject/declarative.py", line 92, in __new__
    cls.__classinit__(cls, new_attrs)

    File "/usr/lib/python2.5/site-packages/sqlobject/main.py", line 762, in __classinit__
    mod = sys.modules[cls.__module__]

    KeyError: '_mp_32178831045d61a426cfbf437900de0b'

    MODULE CACHE DETAILS

    Accessed: Tue May 19 22:40:42 2009
    Generation: 0

    _mp_32178831045d61a426cfbf437900de0b {
    FileName: '/home/michael/public_html/test.py'
    Instance: 1 [IMPORT]
    Generation: 0 [ERROR]
    Modified: Tue May 19 22:35:34 2009
    }

     
  • Oleg Broytman
    Oleg Broytman
    2009-05-19

    • assigned_to: nobody --> phd
     
  • Oleg Broytman
    Oleg Broytman
    2009-05-19

    Uncommenting what lines? Do you mean commenting them out? SQLObject uses mod to find out a global __connection__ declaration.

     
  • damike
    damike
    2009-05-23

    Well by "uncommenting the lines" I meant line 762 and the ones around it so that the main.py of sqlobject is still valid.

    The lines are the following:
    >>>
    if not connection and not getattr(cls, '_connection', None):
    mod = sys.modules[cls.__module__]
    # See if there's a __connection__ global in
    # the module, use it if there is.
    if hasattr(mod, '__connection__'):
    connection = mod.__connection__
    <<<

    The final error in the mod_python error log is:
    >>>
    File "/usr/lib/python2.5/site-packages/sqlobject/main.py", line 762, in
    __classinit__
    mod = sys.modules[cls.__module__]

    KeyError: '_mp_32178831045d61a426cfbf437900de0b'
    <<<

    For me this means that cls.__module__ is equal to '_mp_32178831045d61a426cfbf437900de0b' and it can not be found in the sys.modules hash/array. I am guessing that is because of some magic that mod_python is doing to allow caching/reloading of modules.

    I am not sure if there is another way to find out if there is a connection global but the way it is now does not work with mod_python.

    I am sorry that I can not offer a real patch or fix but I am a novice concerning python.

     
  • damike
    damike
    2009-05-23

    uncommenting = commenting them out

    Sorry, overlooked the real question!

     
  • Oleg Broytman
    Oleg Broytman
    2009-05-23

    How can I detect if SQLObject is running under mod_python? Is there something in sys? os.environ? Can you look it up in mod_python docs? The solution would be something like this:

    if not connection and not getattr(cls, '_connection', None) and \ not running_under_modpython():
    mod = sys.modules[cls.__module__]
    # See if there's a __connection__ global in
    # the module, use it if there is.
    if hasattr(mod, '__connection__'):
    connection = mod.__connection__

    I would like to ask you to find out what 'running_under_modpython' is, test it and send to me.

     
  • I added to the line 761 in main.py of sqlobject
    >>>
    if not connection and not getattr(cls, '_connection', None):
    <<<

    the following check for mod_python:
    >>>
    and not sys.modules.has_key("mod_python"):
    <<<

    So the new line 761 looks as follows:
    >>>
    if not connection and not getattr(cls, '_connection', None) and not sys.modules.has_key("mod_python"):
    <<<

    This seems to work for me. I am not sure if there is a better way than searching the sys.modules dictionary.

    Thanks for your quick reply. I am really wondering why nobody else has stumbled upon this. There are probably a lot of people out there doing mod_python stuff ...

    Well, thanks for your work on sqlobject - I find it really useful!

     
  • Oleg Broytman
    Oleg Broytman
    2009-06-26

    • status: open --> closed-wont-fix
     
  • Oleg Broytman
    Oleg Broytman
    2009-06-26

    It seems mod_python is abandoned. Its author(s) moved to mod_wsgi. Very few people use SQLObject under mod_python. I think it'd be better to leave the patch externally maintained and to recommend people to switch to mod_wsgi.