I have created a Panda3D application that loads model data from an XML file at runtime. This works successfully wshen launched interactively using Run | Run Module menu iten in IDLE.
However, when I create a .p3d file using packp3d and use panda3D.exe to launch it, the application fails to find the XML file.
I am aware of the issues regarding the current directory when Panda3D is launched and so have used base.appRunner.multifileRoot but to no avail.
===========================
Here is a cut down version of my application:
testloadxml.py
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
import urllib
import xml.dom.minidom
from xml.dom.minidom import Node
class World(DirectObject):
def init(self):
fname = “ships.xml”
if base.appRunner:
print "Starting to run in a p3d file"
fname = base.appRunner.multifileRoot+"/ships.xml"
else:
print "Running interactively"
print "loading info file " + fname
self.dom = xml.dom.minidom.parse(urllib.urlopen(fname))
for node in self.dom.getElementsByTagName("ship"):
shipname= node.getAttribute("name")
print shipname
w = World()
run()
Here is the XML file
<?xml version="1.0"?>
==============================================
Here is the batch file I use to build and launch
del testloadxml.p3d
packp3d -o testloadxml.p3d -d testloadxml -m testloadxml.py -p “C:\panda3D-1.7.0\python\Lib” -n xml
panda3D testloadxml.p3d
=============================================
Here is the error I get from running the .p3d file
IOError: [Errno 2] The system cannot find the path specified: ‘\mf\ships.xml’
=============================================
Any help would be much apreciated. It might also help others with similar problems.
if base.appRunner:
print "Starting to run in a p3d file"
fname = base.appRunner.multifileRoot+"/ships.xml"
else:
print "Running interactively"
fnamex = Filename(fname).toOsSpecific()
print "loading info file " + fnamex
self.dom = xml.dom.minidom.parse(urllib.urlopen(fnamex))
================================
Unfortunately, the same problem persists.
I have also used -e to add the XML file to the .p3d file as you also suggested.
It’s because you are using urllib.urlopen(fname) to open your filename. Why that library? It doesn’t know anything about Panda’s vfs. Why not just use open() directly?
The Python’s system open() doesn’t know anything about Panda’s vfs either, but the Panda3D runtime replaces the builtin open() with a new one that does. We didn’t do anything with urllib.urlopen(), though; it never occurred to me that someone would use that library to open a local file.
Many thanks David. You have solved my problem. This now works:
fnamex = Filename(fname).toOsSpecific()
print "loading info file " + fnamex
self.dom = xml.dom.minidom.parse(fnamex)
for node in self.dom.getElementsByTagName("ship"):
shipname= node.getAttribute("name")
print shipname
The reason for using urllib.urlopen is that it was a legacy from my original version of my application that read the XML file from a web site. My aim with the new version is to create self contained installations with the XML embedded. Yet another thing I have learned today.