VirtualFileSystem.readFile and Python 3 strings


#1

I want to check that I’m doing something correctly in the wake of switching from Python 2 to Python 3, if I may.

I have a bit of code that reads a text-file–in this case my “license/credits” file–and then loads it into a TextNode. This is done by simply calling “VirtualFileSystem.readFile”–which returns a string–and then passing the result into “TextNode.setText”.

In Python 2, this worked as expected. In Python 3, it’s a little more complicated: it seems that “readFile” returns a byte-string, and “setText” doesn’t accept those.

My solution right now is to call ‘decode(“utf-8”)’ on the byte-string, returning a Unicode string (if I have it correct). This seems to work.

For reference, here is my current solution in code-form:

vfs = VirtualFileSystem.getGlobalPtr()
creditString = vfs.readFile(Filename("license.txt"), False)
creditString = creditString.decode("utf-8")
creditText.setText(creditString)

However, I’m not confident that I’m doing quite the right thing, or that I have the right codec, or that there won’t be some variance on other operating systems (or even just other machines).

So, am I doing the above correctly? Are there any caveats that I should be aware of here?


#2

If do not use VirtualFileSystem, then normal reading works for me.

from direct.showbase.ShowBase import ShowBase
from direct.gui.OnscreenText import OnscreenText

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        f = open('license.txt', "r")
        data = f.read()
        f.close()
        
        text = OnscreenText(scale=.1)
        text.setText(data)
        

app = MyApp()
app.run()

The only thing I am not sure about is why to put the license file in the panda virtual file system. You still encrypt it :slight_smile:


#3

You can use open() imported from direct.stdpy.file and it will work right with the Virtual File System.

Your current solution seems right too, though. The VFS will only give you a byte result, and you can decode it using whatever encoding you know the file to be in.


#4

My understanding is that using the VirtualFileSystem allows Panda to handle any OS-related variations for me–the same code will do the same thing whether running under Windows or Linux.

I’m not. I’m just using the VirtualFileSystem as a file-reader in this case–the file itself is located in my project folder.

Hmm… The API doesn’t give much information on this–just its parameters. But I see that it includes an “encoding” parameter, so am I guessing that it amounts to much the same as I have above–a “readFile” via the VirtualFileSystem, and decoding via the relevant string method?

Okay, fair enough, and thanks! (I’ll want to remember to double-check what encoding the file uses–it’s not something that I’d thought about previously. ^^; )


#5

As far as I know the cross-platform python, there are of course limitations with the OS module, I would agree if your project was in C ++.


#6

The open function from direct.stdpy.file is designed to be a drop-in replacement for Python’s open() function, so it follows the same parameters. Under the hood, it uses VirtualFileSystem for reading the binary data, but Python’s own io.TextIOWrapper for handling the unicode stuff (unless you open it in binary mode, of course). I think it auto-detects the encoding from the file, but it might also just be using UTF-8, which is what you should be using for your file encoding anyway.

Using open() may make your code easier to understand, but ultimately it doesn’t really matter much whether you use it or use VirtualFileSystem directly. For a small file, it may be easier to read it in one go with readFile().decode().


#7

I don’t recall where I saw the assertion that this was an issue that the VirtualFileSystem solved, but I do vaguely recall it from some time ago. I stand to be corrected, however! shrugs

Ah, I see. That makes sense, I believe! Thank you for the clarification and advice! :slight_smile: