Announcement Announcement Module
Collapse
No announcement yet.
How to access application context from another python module? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to access application context from another python module?

    Hello

    I'm using ApplicationContextAware to access application context from another module, but 'app_context' is always evaluated to None. Here is my code:

    class ApplicationContextProvider(ApplicationContextAware ):

    global_app_ctx = None

    def set_app_context(self, app_context):
    global_app_ctx = app_context

    Then I declare the object in the application context.

    Accessing ApplicationContextProvider.global_app_ctx, gives 'None'.

    What's wrong here?

    Thanks

  • #2
    This assumes that an instance of ApplicationContextProvider is being created inside your application context. Can you post either your PythonConfig, YAML config, or XML config file?

    Comment


    • #3
      Sure, ApplicationContextProvider is being created inside my application context:

      <!-- Context -->
      <object class="test.context.ApplicationContextProvider"></object>
      <!-- End Context -->

      In the main module, I create an instace of a container, and then I can see set_app_ctx is invoked:

      container = ApplicationContext(XMLConfig(config_location=IOUti ls.parse_app_ctx_path()))

      But referencing Accessing ApplicationContextProvider.global_app_ctx from another module, fails

      Comment


      • #4
        Duhh! I now see where you posted that. I'm going to take a crack at coding the same thing, and trying to unravel why it's breaking. Perhaps shed some light on another bug.

        Comment


        • #5
          Okay, I see the problem. It is one of the gotcha's when you use Python's class-level variables. I thought this might be the issue. When you refer to global_app_context inside the set_app_context method, you need to prefix it with the class name, or it will treat it like a local variable.

          Here is my sample where everything is running correctly.

          main.py
          Code:
          from springpython.context import ApplicationContext
          from springpython.config import XMLConfig
          
          from context import ApplicationContextProvider
          import logging
          
          ch = logging.StreamHandler()
          ch.setLevel(logging.DEBUG)
          ch.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
          
          logger = logging.getLogger("springpython")
          logger.setLevel(logging.DEBUG)
          logger.addHandler(ch)
          
          my_logger = logging.getLogger("app_context_aware")
          my_logger.setLevel(logging.DEBUG)
          my_logger.addHandler(ch)
          
          container = ApplicationContext(XMLConfig("app-context.xml"))
          service = container.get_object("ApplicationContextProvider")
          
          my_logger.debug("Service = %s" % service)
          my_logger.debug("Application context = %s" % ApplicationContextProvider.global_app_context)
          
          my_own_instance = ApplicationContextProvider()
          my_logger.debug("Creating my own instance of ApplicationContextProvider => %s" % my_own_instance)
          my_logger.debug("It should have the same app context: %s" % my_own_instance.global_app_context)
          context.py
          Code:
          from springpython.context import ApplicationContextAware
          
          import logging
          
          logger = logging.getLogger("app_context_aware.ApplicationContextProvider")
          
          class ApplicationContextProvider(ApplicationContextAware):
              global_app_context = None
          
              def set_app_context(self, app_context):
                  logger.debug("Updating global_app_context to %s" % app_context)
                  ApplicationContextProvider.global_app_context = app_context
          
          And my app-context.xml file:
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <objects xmlns="http://www.springframework.org/springpython/schema/objects/1.1"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://www.springframework.org/springpython/schema/objects/1.1
                         http://springpython.webfactional.com/schema/context/spring-python-context-1.1.xsd">
          
          	<object id="ApplicationContextProvider"  class="context.ApplicationContextProvider"/>
          
          </objects>
          Here is the output:
          Code:
          (sp)gturnquist-mbp:app_context_aware gturnquist$ python main.py
          2011-10-27 12:23:00,449 - springpython.container.ObjectContainer - DEBUG - === Scanning configuration <springpython.config._xml_config.XMLConfig object at 0x10064f310> for object definitions ===
          2011-10-27 12:23:00,449 - springpython.config.XMLConfig - DEBUG - ==============================================================
          2011-10-27 12:23:00,450 - springpython.config.XMLConfig - DEBUG - * Parsing app-context.xml
          2011-10-27 12:23:00,452 - springpython.config.XMLConfig - DEBUG - object: props = []
          2011-10-27 12:23:00,453 - springpython.config.XMLConfig - DEBUG - object: There are 0 props
          2011-10-27 12:23:00,453 - springpython.config.XMLConfig - DEBUG - ==============================================================
          2011-10-27 12:23:00,453 - springpython.config.XMLConfig - DEBUG - Parsed id=ApplicationContextProvider props=[] scope=scope.SINGLETON factory=ReflectiveObjectFactory(context.ApplicationContextProvider)
          2011-10-27 12:23:00,453 - springpython.container.ObjectContainer - DEBUG - ApplicationContextProvider object definition does not exist. Adding to list of definitions.
          2011-10-27 12:23:00,453 - springpython.container.ObjectContainer - DEBUG - === Done reading object definitions. ===
          2011-10-27 12:23:00,453 - springpython.context.ApplicationContext - DEBUG - Eagerly fetching ApplicationContextProvider
          2011-10-27 12:23:00,453 - springpython.context.ApplicationContext - DEBUG - Did NOT find object 'ApplicationContextProvider' in the singleton storage.
          2011-10-27 12:23:00,453 - springpython.context.ApplicationContext - DEBUG - Creating an instance of id=ApplicationContextProvider props=[] scope=scope.SINGLETON factory=ReflectiveObjectFactory(context.ApplicationContextProvider)
          2011-10-27 12:23:00,453 - springpython.factory.ReflectiveObjectFactory - DEBUG - Creating an instance of context.ApplicationContextProvider
          2011-10-27 12:23:00,453 - springpython.context.ApplicationContext - DEBUG - Stored object 'ApplicationContextProvider' in container's singleton storage
          2011-10-27 12:23:00,454 - app_context_aware.ApplicationContextProvider - DEBUG - Updating global_app_context to <springpython.context.ApplicationContext object at 0x10064f390>
          2011-10-27 12:23:00,454 - app_context_aware - DEBUG - Service = <context.ApplicationContextProvider object at 0x10064f490>
          2011-10-27 12:23:00,454 - app_context_aware - DEBUG - Application context = <springpython.context.ApplicationContext object at 0x10064f390>
          2011-10-27 12:23:00,454 - app_context_aware - DEBUG - Creating my own instance of ApplicationContextProvider => <context.ApplicationContextProvider object at 0x10064ff10>
          2011-10-27 12:23:00,454 - app_context_aware - DEBUG - It should have the same app context: <springpython.context.ApplicationContext object at 0x10064f390>
          2011-10-27 12:23:00,454 - springpython.context.ApplicationContext - DEBUG - Invoking the destroy_method on registered objects
          2011-10-27 12:23:00,454 - springpython.context.ApplicationContext - DEBUG - Successfully invoked the destroy_method on registered objects

          Comment


          • #6
            Did you try to use ApplicationContextProvider inside another module, (ex. test.py)? Hope prefixing the variable with a class name won't raise NoneType error, when trying to get global_app_context (ApplicationContextProvider.global_app_context).

            Thanks : )

            Comment


            • #7
              Tweaking things a bit, it seems to still work. If there is some use case I'm not getting, then please elaborate.

              Code:
              my_own_instance = ApplicationContextProvider()
              my_logger.debug("Creating my own instance of ApplicationContextProvider => %s" % my_own_instance)
              my_logger.debug("It should have the same app context: %s" % my_own_instance.global_app_context)
              my_logger.debug("Globally %s" % ApplicationContextProvider.global_app_context)
              
              my_logger.debug("What about calling another module? %s" % module.testit())
              module.py
              Code:
              from context import ApplicationContextProvider
              
              import logging
              
              def testit():
                  my_logger = logging.getLogger("app_context_aware.module")
              
                  my_logger.debug("ApplicationContextProvider import = %s" % ApplicationContextProvider)
              
                  my_own_instance = ApplicationContextProvider()
                  my_logger.debug("Creating my own instance of ApplicationContextProvider => %s" % my_own_instance)
                  my_logger.debug("It should have the same app context: %s" % my_own_instance.global_app_context)
              
                  my_logger.debug("Modularly %s" % ApplicationContextProvider.global_app_context)
              
                  return ApplicationContextProvider.global_app_context
              output
              Code:
              2011-10-27 15:05:47,703 - app_context_aware - DEBUG - Creating my own instance of ApplicationContextProvider => <context.ApplicationContextProvider object at 0x10064ff50>
              2011-10-27 15:05:47,703 - app_context_aware - DEBUG - It should have the same app context: <springpython.context.ApplicationContext object at 0x10064f3d0>
              2011-10-27 15:05:47,703 - app_context_aware - DEBUG - Globally <springpython.context.ApplicationContext object at 0x10064f3d0>
              2011-10-27 15:05:47,703 - app_context_aware.module - DEBUG - ApplicationContextProvider import = <class 'context.ApplicationContextProvider'>
              2011-10-27 15:05:47,703 - app_context_aware.module - DEBUG - Creating my own instance of ApplicationContextProvider => <context.ApplicationContextProvider object at 0x10064ffd0>
              2011-10-27 15:05:47,703 - app_context_aware.module - DEBUG - It should have the same app context: <springpython.context.ApplicationContext object at 0x10064f3d0>
              2011-10-27 15:05:47,703 - app_context_aware.module - DEBUG - Modularly <springpython.context.ApplicationContext object at 0x10064f3d0>
              2011-10-27 15:05:47,703 - app_context_aware - DEBUG - What about calling another module? <springpython.context.ApplicationContext object at 0x10064f3d0>

              Comment


              • #8
                Regarding NoneType error, if you do an import to get your class into whatever module you are working, it should be available, as long as the application context has had time to be created.

                Comment


                • #9
                  Well, your solution is working because you are calling "testit()" method from the same module where container is being created. I want to have global access to application context from any point of my app, after main module had been executed. Is that possible?

                  Comment


                  • #10
                    I guess I need a use case where this is happening. Are you talking about something like a web container, where one part is the app context, but another part is your module?

                    Comment


                    • #11
                      I'm developing a messaging system based on ZeroMQ, so it's no about web application. In the main module where the container is being instanced, I get various objects from container, message listener, xml-rpc server, etc, and then I initialize them. From another module, call it test.py, I need to get another object from the container (message producer) which will send the message each time the module is executed.
                      Initially I had a global variable (container) inside my main module, but that wasn't a good idea, because each time I execute my test.py module, and reference the global variable, the application context had been reloaded.
                      What I need is some kind of static reference to my message producer once the container bootstrapping is completed, so I can use it module widely.

                      Thank you.

                      Comment


                      • #12
                        There is a possibility that in that architecture, the bootstrapped container and your separate module are running in either separate threads or even separate instances of Python, in which case, you would not be getting what is expected. To tackle that, perhaps if you exported ApplicationContextProvider using PyroServiceExporter, then your client can access it using PyroProxyFactory. You might need a wrapper method to serve up the property, because I don't think properties are exported (yet). Check out http://static.springsource.org/sprin...remote-objects.

                        Comment


                        • #13
                          Okay, My spouse and i see the problem. It happens to be among the list of gotcha's usuallu when you use Python's class-level variables. I was thinking this may be the issue. When you refer to global_app_context from the set_app_context method, it is advisable to prefix it together with the class name, or it will eventually treat it like a local variable.http://houlland.livejournal.com/799.html

                          Comment

                          Working...
                          X