0

My aim is to provide to a web framework access to a Pyro daemon that has time-consuming tasks at the first loading. So far, I have managed to keep in memory (outside of the web app) a single instance of a class that takes care of the time-consuming loading at its initialization. I can also query it with my web app. The code for the daemon is:

Pyro4.expose
@Pyro4.behavior(instance_mode='single')
class Store(object):

    def __init__(self):
        self._store = ... # the expensive loading

    def query_store(self, query):
        return ... # Useful query tool to expose to the web framework.
                   # Not time consuming, provided self._store is
                   # loaded.

with Pyro4.Daemon() as daemon:
    uri = daemon.register(Thing)
    with Pyro4.locateNS() as ns:
        ns.register('thing', uri)
    daemon.requestLoop()

The issue I am having is that although a single instance is created, it is only created at the first proxy query from the web app. This is normal behavior according to the doc, but not what I want, as the first query is still slow because of the initialization of Thing.

How can I make sure the instance is already created as soon as the daemon is started?

I was thinking of creating a proxy instance of Thing in the code of the daemon, but this is tricky because the event loop must be running.

EDIT

It turns out that daemon.register() can accept either a class or an object, which could be a solution. This is however not recommended in the doc (link above) and that feature apparently only exists for backwards compatibility.

mimo
  • 2,469
  • 2
  • 28
  • 49

1 Answers1

1

Do whatever initialization you need outside of your Pyro code. Cache it somewhere. Use the instance_creator parameter of the @behavior decorator for maximum control over how and when an instance is created. You can even consider pre-creating server instances yourself and retrieving one from a pool if you so desire? Anyway, one possible way to do this is like so:

import Pyro4

def slow_initialization():
    print("initializing stuff...")
    import time
    time.sleep(4)
    print("stuff is initialized!")
    return {"initialized stuff": 42}


cached_initialized_stuff = slow_initialization()


def instance_creator(cls):
    print("(Pyro is asking for a server instance! Creating one!)")
    return cls(cached_initialized_stuff)


@Pyro4.behavior(instance_mode="percall", instance_creator=instance_creator)
class Server:
    def __init__(self, init_stuff):
        self.init_stuff = init_stuff

    @Pyro4.expose
    def work(self):
        print("server: init stuff is:", self.init_stuff)
        return self.init_stuff


Pyro4.Daemon.serveSimple({
    Server: "test.server"
})

But this complexity is not needed for your scenario, just initialize the thing (that takes a long time) and cache it somewhere. Instead of re-initializing it every time a new server object is created, just refer to the cached pre-initialized result. Something like this;

import Pyro4

def slow_initialization():
    print("initializing stuff...")
    import time
    time.sleep(4)
    print("stuff is initialized!")
    return {"initialized stuff": 42}


cached_initialized_stuff = slow_initialization()


@Pyro4.behavior(instance_mode="percall")
class Server:
    def __init__(self):
        self.init_stuff = cached_initialized_stuff

    @Pyro4.expose
    def work(self):
        print("server: init stuff is:", self.init_stuff)
        return self.init_stuff


Pyro4.Daemon.serveSimple({
    Server: "test.server"
})
Irmen de Jong
  • 2,739
  • 1
  • 14
  • 26