pythonruntime-errorpanda3d

Panda3d ShowBase multiple Instances


I am currently trying to write a simulator using panda3d. While prototyping I came across a fairly annoying problem. When closing the panda3d window and trying to run a new instance (I am using Spyder as an IDE) it throws an "Exception: Attempt to spawn multiple ShowBase instances".

Unless I completely exit the console I cannot run my code again !

from math import pi, sin, cos
from direct.showbase.ShowBase import ShowBase
from panda3d.core import loadPrcFile
import simplepbr
from direct.task import Task
from panda3d.core import DirectionalLight
from panda3d.core import AntialiasAttrib


loadPrcFile('myconfig.prc')


class World(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)
        simplepbr.init()
        # Load the environment model.
        self.scene = self.loader.loadModel(
            "model/Test.gltf")

        self.scene.reparentTo(self.render)
        self.scene.setScale(20, 20, 20)
        self.scene.setPos(0, 5, 0)

        # Add the spinCameraTask procedure to the task manager.
        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")

        alight = DirectionalLight('alight')
        alight.setColor((1, 1, 1, 1))
        #alight.setShadowCaster(True, 512, 512)
        alnp = self.render.attachNewNode(alight)
        alnp.setHpr(0, -10, 0)
        self.render.setAntialias(AntialiasAttrib.MAuto)
        self.render.setLight(alnp)
        # Define a procedure to move the camera.
        return

    def spinCameraTask(self, task):
        angleDegrees = task.time * 100.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.camera.setPos(40 * sin(angleRadians), -
                           40.0 * cos(angleRadians), 10)
        self.camera.setHpr(angleDegrees, -5, 0)
        return Task.cont
app = World()
app.run()

So I am fairly at a loss of explanation why this happens. Searching the net also gave me many results that this problem occurs since 2013 and even tried many solution strategies from which some don't work anymore due to version changes and some just are not applicable. For instance Here Question: Can anyone give me a direction what is wrong with my code or how to circumvent this behavior ?


Solution

  • From your description I'm assuming you're not trying to open multiple windows simultaneously but instead sequentially, one after another gets closed, without exiting the Python interpreter.

    tl;dr

    Call app.destroy() before running app = World() again.

    Explanation

    Panda3d sets up global variables when the first instance of ShowBase gets created, among them a global variable called base holding a reference to the ShowBase instance. If you try to create another ShowBase instance afterwards Panda3d will check if the base global is defined and will throw an Attempt to spawn multiple ShowBase instances! exception if one already exists.

    You need to clean up the previous ShowBase instance before creating a new window. Panda3d sets up an atexit cleanup function that cleans up the global state, but since you're not exiting the interpreter you're not triggering the cleanup. You can do the same thing as the cleanup function manually, which is to call .destroy() on the ShowBase instance. This will remove the global references and allow you to create another instance of ShowBase.

    In [1]: from direct.showbase.ShowBase import ShowBase
    In [2]: window = ShowBase()
    In [3]: window.run() # Run the main loop, closing the window stops the main loop
    In [4]: window.destroy()  # Manually clean up the old window
                              # `base.destroy()` would also work
    In [5]: window = ShowBase()  # No errors after destroying the old window
    In [6]: window.run()