การสร้างอินสแตนซ์แบบไม่ขี้เกียจด้วย Pyro4 และ instance_mode='single'

เป้าหมายของฉันคือเพื่อให้เว็บเฟรมเวิร์กสามารถเข้าถึง Pyro daemon ซึ่งมีงานที่ใช้เวลานานในการโหลดครั้งแรก จนถึงตอนนี้ ฉันจัดการเพื่อเก็บอินสแตนซ์เดียวของคลาสที่ดูแลการโหลดที่ใช้เวลานานในการเริ่มต้นไว้ในหน่วยความจำ (นอกเว็บแอป) ฉันยังสามารถสอบถามด้วยเว็บแอปของฉันได้ รหัสสำหรับ daemon คือ:

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()

ปัญหาที่ฉันมีคือแม้ว่าจะมีการสร้างอินสแตนซ์เดียว แต่อินสแตนซ์นั้นจะถูกสร้างขึ้นเฉพาะในการสืบค้นพร็อกซีแรกจากเว็บแอปเท่านั้น นี่เป็นพฤติกรรมปกติตาม doc แต่ไม่ใช่สิ่งที่ฉันต้องการ เนื่องจากการสืบค้นแรกยังคงช้าเนื่องจากการเริ่มต้นของ Thing

ฉันจะแน่ใจได้อย่างไรว่าอินสแตนซ์นั้นถูกสร้างขึ้นทันทีที่ daemon เริ่มทำงาน

ฉันกำลังคิดที่จะสร้างอินสแตนซ์พร็อกซีของ Thing ในโค้ดของ daemon แต่นี่เป็นเรื่องยากเนื่องจากลูปเหตุการณ์จะต้องทำงานอยู่

แก้ไข

ปรากฎว่า daemon.register() สามารถยอมรับคลาสหรืออ็อบเจ็กต์ได้ ซึ่งอาจเป็นวิธีแก้ปัญหา อย่างไรก็ตาม ไม่แนะนำสิ่งนี้ในเอกสาร (ลิงก์ด้านบน) และดูเหมือนว่าฟีเจอร์นั้นมีไว้เพื่อความเข้ากันได้แบบย้อนหลังเท่านั้น


person mimo    schedule 01.02.2018    source แหล่งที่มา


คำตอบ (1)


ทำการเริ่มต้นใดๆ ก็ตามที่คุณต้องการนอกเหนือจากรหัส Pyro แคชไว้ที่ไหนสักแห่ง ใช้พารามิเตอร์ instance_creator ของมัณฑนากร @behavior เพื่อการควบคุมสูงสุดเกี่ยวกับวิธีการและเวลาในการสร้างอินสแตนซ์ คุณยังสามารถพิจารณาสร้างอินสแตนซ์เซิร์ฟเวอร์ล่วงหน้าด้วยตัวเองและดึงข้อมูลจากพูลได้หากต้องการ อย่างไรก็ตาม วิธีหนึ่งที่เป็นไปได้คือ:

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"
})

แต่ความซับซ้อนนี้ไม่จำเป็นสำหรับสถานการณ์ของคุณ เพียงแค่เริ่มต้นสิ่งนั้น (ที่ใช้เวลานาน) และแคชไว้ที่ไหนสักแห่ง แทนที่จะเริ่มต้นใหม่ทุกครั้งที่สร้างออบเจ็กต์เซิร์ฟเวอร์ใหม่ เพียงอ้างอิงถึงผลลัพธ์ที่เตรียมใช้งานล่วงหน้าที่แคชไว้ อะไรประมาณนี้;

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"
})
person Irmen de Jong    schedule 02.02.2018