Failure to load an XML file inside a .p3d file

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.

Hi, welcome to the forums!

Hm, just a guess, but you may need to convert the path into an OS-specific path using Filename(fname).toOsSpecific() .

Furthermore, I see you’re using “-n xml”, but it would be beneficial to enable compression for xml files by using the “-e xml” option instead.

Also, consider using

[code]
tags when you post code in forum posts.

The Python indentation got lost in creating the first post. Can anyone tell me how I can upload Python in these posts preserving the indentation?

The intent of the code should be clear anyway.

Yes, it is possible to preserve indentation by using

[code]
tags, as I recommended in my previous post.

Thanks for the tip about using the code tags.

I have amended the code as you suggest to give:

      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.

David

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.

Brian