Doc:Tutorials/Extensions/Python/BSoD/Importers-Exporters
From BlenderWiki
Contents |
[edit] Python File Input/Output
Files come in two flavors: text and binary.
- Text files are readable by humans. They contain words or numbers you can read when you print them or look at them in a text editor.
- Binary files contain pure numbers coded as ones and zeros and seem to contain random characters or noise when you look at them. Programs, like Blender, that create lots of numeric data tend to store their data in binary format.
This would be a good time to read Section 7 of the Python Tutorial, particularly 7.2 Reading and Writing Files. If you are reading or writing binary files, the Python struct module is your friend.
[edit] Program: Read/Write
To create a file we use the built-in open() command which creates a file object. We need to provide the name of the file and a mode, either read or write. Once we get the file object from open() we call read() and write() methods on it. These methods work much like the print command. When we are done with a file, we call the close() method.
Let's modify our old name printing script to write a file of object names, one name per line. This version gets a list of all objects in the current scene, writes their names to a file and then reads them back in, printing to the console.
note:: the reason we use scene.getChildren() rather than Object.Get() is that Object.Get() returns all the objects in the .blend file. Calling scene.getChildren() only returns the objects in the current scene.
import Blender as B
scene = B.Scene.getCurrent()
ob_list = scene.getChildren()
# create a file for writing
try:
outfile = open('myText.txt', 'w')
for ob in ob_list:
# write each object name followed by a newline character
outfile.write( ob.name + '\n' )
outfile.close()
except:
print 'Oh no! something went wrong'
else:
if outfile: outfile.close()
print 'done writing'
# open the file we just wrote
try:
infile = open('myText.txt', 'r')
for line in infile:
print line
except:
print 'Error reading file'
else:
infile.close()
print 'done'
[edit] Program: Export
Our next example is a simple exporter that writes object names and coordinates to a text file, one object per line. We will use formated output to create our strings for writing.
import Blender as B
scene = B.Scene.getCurrent()
ob_list = scene.getChildren()
# create a file for writing
# our file format is
# object-name x-coord y-coord z-coord
try:
outfile = open('export.dat', 'w')
for ob in ob_list:
# write object name and coords followed by a newline
x, y, z = ob.loc # unpack the ob.loc tuple for printing
outfile.write( "%s %f %f %f\n" % ( ob.name, x, y, z) )
outfile.close()
except Exception, e:
print 'Oh no! something went wrong:', e
else:
if outfile: outfile.close()
print 'done writing'
[edit] Program: Import
This example is a simple importer to process data from our exporter. For each line of data, we split the line into a name and the x,y,z coordinates. The we create an Empty as a ghost in the same location.
Points to note:
This script has two parts - a main routine and a defined function to handle each line of text we read. By factoring out the handle_line() method, we make the complexity of our scripts easier to manage. For a simple script like this, it does not matter as much, but as our scripts get longer and more complex, isolating functionality makes it easier to write and maintain our code. In this example, if we want to change how we handle a line of input, only the handle_line() function needs to change. We do not need to touch the main routine.
import Blender as B
#
# process each line of a data file
# create an Empty in the same location as each object
#
def handle_line( line ):
print line
# chop up line into name and coordinates
# remember these are all strings
name, xs, ys, zs = line.split()
print name, xs, ys, zs
scene = B.Scene.getCurrent()
# create a new Empty named Empty-xxx
empty = B.Object.New('Empty', 'Empty-' + name)
# convert our number strings to floats
empty.loc = float(xs), float(ys), float(zs)
scene.link(empty) # link our new object into scene
#
# main
#
infile = open('export.dat', 'r')
try:
for line in infile:
handle_line( line )
except Exception, e:
print 'Oops!', e
B.Redraw(-1)
