Maya Python for Games and Film A Complete Reference for Maya Python and the Maya Python API 1st Edition Adam Mechtley - Download the entire ebook instantly and explore every detail
Maya Python for Games and Film A Complete Reference for Maya Python and the Maya Python API 1st Edition Adam Mechtley - Download the entire ebook instantly and explore every detail
com
https://ebookgate.com/product/maya-python-for-games-and-
film-a-complete-reference-for-maya-python-and-the-maya-
python-api-1st-edition-adam-mechtley/
OR CLICK HERE
DOWLOAD NOW
https://ebookgate.com/product/practical-maya-programming-with-
python-1st-edition-galanakis/
ebookgate.com
https://ebookgate.com/product/python-the-complete-manual-the-
essential-handbook-for-python-users-master-python-today-first-edition-
unknown/
ebookgate.com
https://ebookgate.com/product/black-hat-python-python-programming-for-
hackers-and-pentesters-1st-edition-seitz/
ebookgate.com
https://ebookgate.com/product/python-for-beginners-2018-edition-learn-
to-code-with-python-mark-lassoff/
ebookgate.com
Python Essential Reference 3rd Edition Beazley
https://ebookgate.com/product/python-essential-reference-3rd-edition-
beazley/
ebookgate.com
https://ebookgate.com/product/mel-scripting-for-maya-animators-1st-
edition-mark-r-wilkins/
ebookgate.com
https://ebookgate.com/product/python-pocket-reference-5ed-edition-
mark-lutz/
ebookgate.com
https://ebookgate.com/product/python-for-finance-1st-edition-yuxing-
yan/
ebookgate.com
https://ebookgate.com/product/python-tricks-a-buffet-of-awesome-
python-features-dan-bader/
ebookgate.com
Chapter
CHAPTER OUTLINE
Interacting with Maya 4
Maya Embedded Language 5
Python 5
C++ Application Programming Interface 6
Python API 6
Executing Python in Maya 6
Command Line 6
Script Editor 8
Maya Shelf 10
Maya Commands and the Dependency Graph 11
Introduction to Python Commands 15
Flag Arguments and Python Core Object Types 19
Numbers 20
Strings 20
Lists 20
Tuples 21
Booleans 21
Flag = Object Type 21
Command Modes and Command Arguments 22
Create Mode 22
Edit Mode 23
Query Mode 23
Python Command Reference 24
Synopsis 25
Return Value 25
Related 25
Flags 25
Python Examples 26
Python Version 26
Python Online Documentation 26
Concluding Remarks 27
Maya Python for Games and Film. DOI: 10.1016/B978-0-12-378578-7.00001-6
© 2012 Elsevier Inc. All rights reserved. 3
4 CHAPTER 1 Maya Command Engine and User Interface
To fully understand what can be done with Python in Maya, we must first
discuss how Maya has been designed. There are several ways that users
can interact with or modify Maya. The standard method is to create content
using Maya’s graphical user interface (GUI). This interaction works like any
other software application: Users press buttons or select menu items that
create or modify their documents or workspaces. Despite how similar Maya
is to other software, however, its underlying design paradigm is unique in
many ways. Maya is an open product, built from the ground up to be capable
of supporting new features designed by users. Any Maya user can modify or
add new features, which can include a drastic redesign of the main interface
or one line of code that prints the name of the selected object.
In this chapter, we will explore these topics as you begin programming in
Python. First, we briefly describe Maya’s different programming options and
how they fit into Maya’s user interface. Next, we jump into Python by exploring
different means of executing Python code in Maya. Finally, we explore some
basic Maya commands, the primary means of modifying the Maya scene.
Python
Python is a scripting language that was formally introduced to Maya in
version 8.5. Python can execute the same Maya commands as MEL using
Maya’s Command Engine. However, Python is also more robust than MEL
because it is an object-oriented language. Moreover, Python has existed
since 1980 and has an extensive library of built-in features as well as a
large community outside of Maya users.
6 CHAPTER 1 Maya Command Engine and User Interface
Python API
When Autodesk introduced Python into Maya, they also created wrappers
for many of the classes in the Maya C++ API. As such, developers can use
much of the API functionality from Python. The total scope of classes acces-
sible to the Python API has grown and improved with each new version of
Maya. This powerful feature allows users to manipulate Maya API objects
in ordinary scripts, as well as to create plug-ins that add new features to Maya.
In this book, we focus on the different uses of Python in Maya, including
commands, user interfaces, and the Python API. Before we begin our
investigation, we will first look at the key tools that Maya Python program-
mers have at their disposal.
Command Line
The first tool of interest is the Command Line. It is located along the
bottom of the Maya GUI. You can see the Command Line highlighted in
Figure 1.2.
The Command Line should appear in the Maya GUI by default. If you
cannot see the Command Line, you can enable it from the Maya main
menu by selecting Display → UI Elements → Command Line.
The far left side of the Command Line has a toggle button, which says
“MEL” by default. If you press this button it will display “Python.”
Executing Python in Maya 7
The language displayed on this toggle button tells Maya which scripting
language to use when executing commands entered in the text field imme-
diately to the right of the button. The right half of the Command Line, a
gray bar, displays the results of the commands that were entered in the text
field. Let’s create a polygon sphere using the Command Line.
1. Switch the Command Line button to “Python.” The button is located on
the left side of the Command Line.
2. Click on the text field in the Command Line and enter the following
line of text.
import maya.cmds;
3. Press Enter.
4. Next enter the following line of code in the text field.
maya.cmds.polySphere();
5. Press Enter. The above command will create a polygon sphere object
in the viewport and will print the following results on the right side
of the Command Line.
# Result: [u'pSphere1', u'polySphere1']
8 CHAPTER 1 Maya Command Engine and User Interface
You can use the Command Line any time you need to quickly execute a
command. The Command Line will only let you enter one line of code at
a time though, which will not do you much good if you want to write a
complicated script. To perform more complex operations, you need the
Script Editor.
Script Editor
One of the most important tools for the Maya Python programmer is the Script
Editor. The Script Editor is an interface for creating short scripts to interact
with Maya. The Script Editor (shown on the right side in Figure 1.2) consists
of two panels. The top panel is called the History Panel and the bottom panel
is called the Input Panel. Let’s open the Script Editor and execute a command
to make a sphere.
1. Open a new scene by pressing Ctrl + N.
2. Open the Script Editor using either the button located near the bottom
right corner of Maya’s GUI, on the right side of the Command Line
(highlighted in Figure 1.2), or by navigating to Window → General
Editors → Script Editor in Maya’s main menu. By default the Script
Editor displays two tabs above the Input Panel. One tab says “MEL”
and the other tab says “Python.”
3. Select the Python tab in the Script Editor.
4. Click somewhere inside the Input Panel and type the following lines of
code.
import maya.cmds;
maya.cmds.polySphere();
5. When you are finished press the Enter key on your numeric keypad. If
you do not have a numeric keypad, press Ctrl + Return.
The Enter key on the numeric keypad and the Ctrl + Return shortcut are
used only for executing code when working in the Script Editor. The reg-
ular Return key simply moves the input cursor to the next line in the Input
Panel. This convention allows you to enter scripts that contain more than
one line without executing them prematurely.
Just as in the Command Line example, the code you just executed created a
generic polygon sphere. You can see the code you executed in the History
Panel, but you do not see the same result line that you saw when using the
Command Line. In the Script Editor, you will only see a result line printed
when you execute a single line of code at a time.
6. Enter the same lines from step 4 into the Input Panel, but do not execute
them.
Executing Python in Maya 9
7. Highlight the second line with your cursor by triple-clicking it and then
press Ctrl + Return. The results from the last command entered should
now be shown in the History Panel.
# Result: [u'pSphere2', u'polySphere2']
Apart from printing results, there are two important things worth noting
about the previous step. First, highlighting a portion of code and then press-
ing Ctrl + Return will execute only the highlighted code. Second, high-
lighting code in this way before executing it prevents the contents of the
Input Panel from emptying out.
Another useful feature of the Script Editor is that it has support for marking
menus. Marking menus are powerful, context-sensitive, gesture-based
menus that appear throughout the Maya application. If you are unfamiliar
with marking menus in general, we recommend consulting any basic Maya
user’s guide.
To access the Script Editor’s marking menu, click and hold the right mouse
button (RMB) anywhere in the Script Editor window. If you have nothing
selected inside the Script Editor, the marking menu will allow you to
quickly create new tabs (for either MEL or Python) as well as navigate
between the tabs. As you can see, clicking the RMB, quickly flicking to
the left or right, and releasing the RMB allows you to rapidly switch
between your active tabs, no matter where your cursor is in the Script Edi-
tor window. However, the marking menu can also supply you with context-
sensitive operations, as in the following brief example.
1. Type the following code into the Input Panel of the Script Editor, but
do not execute it.
maya.cmds.polySphere()
2. Use the left mouse button (LMB) to highlight the word polySphere in
the Input Panel.
3. Click and hold the RMB to open the Script Editor’s marking menu. You
should see a new set of options in the bottom part of the marking menu.
4. Move your mouse over the Command Documentation option in the
bottom of the marking menu and release the RMB. Maya should
now open a web browser displaying the help documentation for the
polySphere command.
As you can see, the Script Editor is a very useful tool not only for creating
and executing Python scripts in Maya, but also for quickly pulling up infor-
mation about commands in your script. We will look at the command
documentation later in this chapter.
10 CHAPTER 1 Maya Command Engine and User Interface
Maya Shelf
Now that you understand how to use the Command Line and the Script
Editor, it is worth examining one final tool in the Maya GUI that will be
valuable to you. Let’s say you write a few lines of code in the Script Editor
and you want to use that series of commands later. Maya has a location for
storing custom buttons at the top of the main interface, called the Shelf,
which you can see in Figure 1.3. If you do not see the Shelf in your GUI
layout, you can enable it from Maya’s main menu using the Display →
UI Elements → Shelf option.
You can highlight lines of code in the Script Editor or Command Line and
drag them onto the Shelf for later use with the middle mouse button
(MMB). In the following example, you will create a short script and save it
to the Shelf.
1. Type in the following code into the Script Editor, but do not execute
it (when executed, this script will create a polygon sphere and then
change the sphere’s vertex colors to red).
import maya.cmds;
maya.cmds.polySphere(radius=5);
maya.cmds.polyColorPerVertex(
colorRGB=[1,0,0],
colorDisplayOption=True
);
2. Click the Custom tab in the Shelf. You can add buttons to any shelf, but
the Custom shelf is a convenient place for users to store their own
group of buttons.
3. Click and drag the LMB over the script you typed into the Script Editor
to highlight all of its lines.
4. With your cursor positioned over the highlighted text, click and hold
the MMB to drag the contents of your script onto the Shelf.
5. If you are using Maya 2010 or an earlier version, a dialog box will
appear. If you see this dialog box, select “Python” to tell Maya that
the script you are pasting is written using Python rather than MEL.
6. You will now see a new button appear in your Custom tab. Left-click on
your new button and you should see a red sphere appear in your viewport
as in Figure 1.3. If you are in wireframe mode, make sure you enter shaded
mode by clicking anywhere in your viewport and pressing the number 5 key.
You can edit your Shelf, including tabs and icons, by accessing the
Window → Settings/Preferences → Shelf Editor option from the main
Maya window. For more information on editing your Shelf, consult the
Maya documentation or a basic Maya user’s guide. Now that you have an
understanding of the different tools available in the Maya GUI, we can start
exploring Maya commands in greater detail.
data—creation, destruction, editing, and so on. All of the data in the core are
represented by a set of objects called nodes and a series of connections that
establish relationships among these nodes. Taken together, this set of relation-
ships among nodes is called the Dependency Graph (DG).
For example, the polygon sphere object you created earlier returned the
names of two nodes when you created it: a node that describes the geome-
try of the sphere and a transform node that determines the configuration of
the sphere shape in space. You can see information on nodes in an object’s
network using the Attribute Editor (Window → Attribute Editor in the
main menu) or as a visual representation in the Hypergraph (Window →
Hypergraph: Connections in the main menu). Because this point is so
important, it is worth looking at a brief example.
1. If you no longer have a polygon sphere in your scene, create one.
2. With your sphere object selected, open the Hypergraph displaying
connections by using the Window → Hypergraph: Connections option
from the main menu.
3. By default, the Hypergraph should display the connections for your
currently selected sphere as in Figure 1.4. If you do not see anything,
then select the option Graph → Input and Output Connections from
the Hypergraph window’s menu.
As you can see, a default polygon sphere consists of four basic nodes
connected by a sequence of arrows that show the flow of information. The
first node in the network is a polySphere node, which contains the para-
meters and functionality for outputting spherical geometry (e.g., the radius,
the number of subdivisions, and so on). In fact, if you highlight the arrow
showing the connection to the next node, a shape node, you can see what
data are being sent. In this case, the polySphere node’s output attribute is
piped into the inMesh attribute of the shape node.
If you were to delete the construction history of this polygonal sphere
(Edit → Delete by Type → History from the main menu), the polySphere
node would disappear and the sphere’s geometry would then be statically
stored in the shape node (pSphereShape1 in Figure 1.4). In short, if the
polySphere node were destroyed, its mesh information would be copied into
the pSphereShape node, and you would no longer be able to edit the radius
or number of subdivisions parametrically; you would have to use modeling
tools to do everything by hand.
While you can also see that information is piped from the shape node into a
shadingGroup node (to actually render the shape), there is a node that
appears to be floating on its own (pSphere1 in Figure 1.4). This separate
node is a special kind of object, a transform node, which describes the posi-
tion, scale, and orientation of the polygonal sphere’s geometry in space. The
reason why this node is not connected is because it belongs to a special part
of the DG, called the Directed Acyclic Graph (DAG). For right now, it suf-
fices to say that the DAG essentially describes the hierarchical relationship of
objects that have transform nodes, including what nodes are their parents
and what transformations they inherit from their parents.
The Maya DG is discussed in greater detail in Chapter 11 in the context of
the Maya API, yet this principle is critical for understanding how Maya
works. We strongly recommend consulting a Maya user guide if you feel
like you need further information in the meantime.
Although Maya is, as we pointed out, an open product, the data in the core
are closed to users at all times. Autodesk engineers may make changes
to the core from one version to another, but users may only communicate
with the application core through a defined set of interfaces that Autodesk
provides.
One such interface that can communicate with the core is the Command
Engine. In the past, Maya commands have often been conflated with
14 CHAPTER 1 Maya Command Engine and User Interface
documentation and are not directly available to Python. Again, this absence
is also not a limitation, as it is possible to execute MEL scripts with Python
when needed. Likewise, MEL can call Python commands and scripts when
required.1
Another important feature of the Maya Command Engine is how easy it is to
create commands that work for MEL and Python. Maya was designed so that
any new command added will be automatically available to both MEL and
Python. New commands can be created with the Maya C++ API or the Python
API. Now that you have a firmer understanding of how Maya commands fit
into the program’s architecture, we can go back to using some commands.
The first line shown is the polyCube MEL command, which is very similar
to the polySphere command we used earlier in this chapter. As you can see,
1
MEL can call Python code using the python command. Python can call MEL code
using the eval function in the maya.mel module. Note that using the python command
in MEL executes statements in the namespace of the __main__ module. For more infor-
mation on namespaces and modules, see Chapter 4.
16 CHAPTER 1 Maya Command Engine and User Interface
a MEL command was called when you selected the Cube option in the
Polygon Primitives menu. That MEL command was displayed in the
Script Editor’s History Panel.
Because Maya’s entire interface is written with MEL, the History Panel
always echoes MEL commands when using the default Maya interface.
Custom user interfaces could call the Python version of a command, in
which case the History Panel would display the Python command.
This problem is not terribly troublesome for Python users though. It does
not take much effort to convert a MEL command into Python syntax, so
this feature can still help you learn which commands to use. The following
example shows what the polyCube command looks like with Python.
import maya.cmds;
maya.cmds.polyCube(
w=1, h=1, d=1, sx=1, sy=1, sz=1,
ax=(0, 1, 0), cuv=4, ch=1
);
If you execute these lines of Python code they will produce the same result as
the MEL version. However, we need to break down the Python version of the
command so we can understand what is happening. Consider the first line:
import maya.cmds;
Introduction to Python Commands 17
This line of code imports a Python module that allows you to use any Maya
command available to Python. There is only one module that holds all
Maya commands and you only need to import it once per Maya session.
Once it is in memory you don’t need to import it again (we only have
you reimport it for each example in case you’re picking the book back
up after a break from Maya). We will discuss modules in greater depth in
Chapter 4. The next line of code is the Python command.
maya.cmds.polyCube(
w=1, h=1, d=1, sx=1, sy=1, sz=1,
ax=(0, 1, 0), cuv=4, ch=1
);
As you can see, the name of the command, polyCube, is prefixed by the
name of the module, maya.cmds. The period between them represents that
this command belongs to the Maya commands module. We then supply the
command several flag arguments inside of parentheses. A key-value pair
separated by the equals sign, such as w=1, represents the name and value
for the flag argument, and each of these pairs is separated by a comma.
The long names are easier to read and so it can be good practice to use them
when scripting. Code that is easier to read can be much easier to work with—
especially if you or a coworker has to make any changes several months later!
You may now be wondering how to find the long flag names in the future.
1. Type the following lines into the Script Editor and press Ctrl + Return
to execute them.
import maya.cmds;
print(maya.cmds.help('polyCube'));
18 CHAPTER 1 Maya Command Engine and User Interface
2. Look for the results in the History Panel, which should look like the
following lines.
Synopsis: polyCube [flags] [String...]
Flags:
–e –edit
–q –query
–ax –axis Length Length Length
–cch –caching on|off
–ch –constructionHistory on|off
–cuv –createUVs Int
–d –depth Length
–h –height Length
–n –name String
–nds –nodeState Int
–o –object on|off
–sd –subdivisionsDepth Int
–sh –subdivisionsHeight Int
–sw –subdivisionsWidth Int
–sx –subdivisionsX Int
–sy –subdivisionsY Int
–sz –subdivisionsZ Int
–tx –texture Int
–w –width Length
As you can see, the result first displays the command for which help was
requested—polyCube in this case. The following items in brackets, [flags]
and [String...], show MEL syntax for executing the command. In
MEL, the command is followed by any number of flag arguments and then
any number of command arguments. We’ll differentiate these two items
momentarily.
Next, the output shows the list of flags for the command, displaying the
short name on the left, followed by the long name in the middle column.
Each flag is prefixed by a minus symbol, which is required to indicate a
flag in MEL syntax, but which you can ignore in Python. To the very right
of each flag name is the data type for each argument, which tells us what
kind of value each flag requires.
We can see how flags work with the polyCube command. Consider the
following example.
import maya.cmds;
maya.cmds.polyCube();
Executing this command causes Maya to create a polygon cube with default
properties. The parentheses at the end of the command basically indicate that
Flag Arguments and Python Core Object Types 19
If you execute the previous lines, Maya will create a polygon cube named
“myCube” with a depth of 12.5 units and a height of 5 units. The first flag
we set, name, is a string, as indicated in the help results. A string is a sequence
of letters and numbers inside of quotation marks, and is used to represent a
word or words. Immediately afterward is a comma before the next flag, depth.
We specify that the depth should be the decimal number 12.5. Such values are
listed as type Length in the help results. Last, we provided the height flag and
supplied a value of 5. In this case, we used the long names of the flags, but we
could also have used the short ones to do the same thing.
import maya.cmds;
maya.cmds.polyCube(n='myCube', d=12.5, h=5);
Looking at the help results, you can see that the axis flag takes three decimal
numbers. To specify this kind of argument in Python, we use what is called
a tuple. A tuple is basically a sequence of objects inside of parentheses, sepa-
rated by commas. The following lines show an example of the same command
using a tuple to specify a different axis.
import maya.cmds;
maya.cmds.polyCube(
name='myCube',
depth=12.5,
height=5,
axis=(1,1,0)
);
Numbers 1
−5
3.14159
9.67
Strings "Maya"
'ate'
"my dog's"
"""homework"""
Lists [1, "horse", 'town']
Tuples (1, "two", 'three')
Booleans True
False
1
0
However, the core object types in this list are the only ones that Maya
commands have been designed to use, so we may ignore the others for now.
Other Python data types are discussed in Chapter 2. Let’s focus for now on
the five types in this list.
Numbers
Maya commands expecting Python numbers will accept any real number.
Examples could include integer as well as decimal numbers, which corre-
spond to int/long and float/double types, respectively, in other languages.
Strings
The string type is any sequence of letters or numbers enclosed in single quota-
tion marks, double quotation marks, or a matching pair of triple quotation
marks of either type. For instance, “boat”, “house”, and “car” are equivalent
to ‘boat’, ‘house’, and ‘car’ as well as to “““boat”””, “““house”””, and
“““car”””. However, the string “3” is different from the number object 3.
Strings are typically used to name objects or parameters that are accessible
from the Maya user interface.
Lists
A list is a sequence of any number of Python objects contained within the
bracket characters [ and ]. A comma separates each object in the list. Any
Python object may be in a list, including another list!
Flag Arguments and Python Core Object Types 21
Tuples
The Python tuple is very similar to the list type except that it is not muta-
ble, which means it cannot be changed. We discuss mutability in greater
detail in Chapter 2. Tuples are contained inside of ordinary parentheses,
( and ).
Booleans
A Boolean value in Python can be the word True or False (which must
have the first letter capitalized), or the numbers 1 and 0 (which correspond
to the values True and False, respectively). These values are typically used
to represent states or toggle certain command modes or flags.
3. Look for the width flag in the results displayed in the History Panel
and find its argument type on the right side:
–w –width Length
As you can see, the width flag requires a Length type argument, as shown
to the right of the flag name. This is technically not a Python type but we
can deduce that Length means a number, so we should pass this flag some
sort of number. If the number needed to be a whole number, the flag would
specify Int to the right of the flag instead of Length. We can therefore also
deduce that the flag may be passed a decimal number in this case. Let’s
first pass a correct argument.
4. Type the following command into the Script Editor and press Ctrl +
Return to execute it.
maya.cmds.polyCube(width=10);
22 CHAPTER 1 Maya Command Engine and User Interface
You should see the following result in the Script Editor’s History Panel.
# Result: [u'pCube1', u'polyCube1'] #
The result lets us know that the command succeeded and also shows that the
command returned a Python list containing the names of two new nodes that
have been created to make our cube object: “pCube1” (a transform node)
and “polyCube1” (a shape node). Now, let’s see what happens when we inten-
tionally supply the width flag with the wrong data type.
5. Type the following command into the Script Editor and press Ctrl +
Return to execute it.
maya.cmds.polyCube(width='ten');
The error tells you that the argument for the width flag was incorrect and it
expected a distance value. Even though the help command showed the
width flag needed a Length type, Maya is now calling it a distance type.
This can be confusing at first but most of the time it is very clear what
the flag argument requires simply by looking at the flag in context. The
help command does not describe what each flag does, but you can get
more detailed descriptions using the Python Command Reference, which
we will examine shortly.
Create Mode
Most commands at least have a create mode. This mode allows users to
create new objects in the scene and specify any optional parameters. By
default, the polyCube command operates in create mode.
1. Create a new Maya scene.
2. Execute the following lines in the Script Editor to create a new cube.
import maya.cmds;
maya.cmds.polyCube();
Edit Mode
Another mode that many commands support is edit mode. This mode
allows users to edit something the command has created.
3. Execute the following line in the Script Editor to change the cube’s
width.
maya.cmds.polyCube('pCube1', edit=True, width=10);
As you can see, you specified that the command should operate in edit
mode by setting the edit flag with a value of True. In edit mode, you were
able to change the width of the object named “pCube1” to a value of 10. It
is worth mentioning that some flags in MEL do not require an argument,
such as the edit flag (see help output previously). Such flags, when
invoked from Python, simply require that you set some value (True) to
indicate their presence.
Another important point worth noting is the syntax for operating in edit and
query modes. The first argument we pass to the command is called a
command argument, and specifies the name of the node on which to operate.
As we saw in the help output previously, MEL syntax expects command
arguments to follow flag arguments, while Python requires the opposite
order. The reason for Python’s syntax requirement will be discussed in
greater detail in Chapter 3. Leave the cube in the scene for the next step.
Query Mode
The last mode that many commands support is query mode. This mode
permits users to request information about something the command has
already created.
4. Execute the following line in the Script Editor to print the cube’s width.
maya.cmds.polyCube('pCube1', query=True, width=True);
The result in the History Panel should display something like the
following line.
# Result: 10.0 #
As with edit mode, query mode requires that you specify a command argu-
ment first and then set the query flag with a value of True. Another point
worth noting is that, although the width flag normally requires a decimal
number (when being invoked from create or edit mode), you simply pass
it a value of True in query mode. The basic idea is that in this case, the
Command Engine is only interested in whether or not the flag has been
set, and so it will not validate the value you are passing it.
24 CHAPTER 1 Maya Command Engine and User Interface
As you can see, these three modes allowed you to create an object, change
it, and finally pull up information about its current state. We also noted at
the outset of this section that some flags are only compatible with certain
command modes. While the help command will not give you this informa-
tion, the Command Reference documentation will.
Synopsis
The synopsis provides a short description of what the command does. In
this case the synopsis states:
polyCube is undoable, queryable, and editable.
The cube command creates a new polygonal cube.
Return Value
The return value section describes what the command will return when it is
executed. In this case the documentation states:
string[] Object name and node name.
This description shows us that it returns a list of string type objects, which
will be the name of the object (transform node) and the (polyCube) node
that were created.
Related
This section can help you with finding commands that are similar to the
command at which you are looking. For the polyCube command, this
section lists other commands for creating primitive polygon objects:
polyCone, polyCylinder, polyPlane, polySphere, polyTorus
Flags
For the polyCube command, the axis flag is listed first. It shows a short
description of what the flag does and then it lists the argument type to pass
to it. The documentation shows the following text:
[linear, linear, linear]
The command requires a Python list (or tuple) type and that list should hold
three real numbers. If int is not specified for an argument type, then the argu-
ment may be a decimal number, though integer numbers are still valid. In
this case, if we were to define the argument for the flag it could be something
like [1.00, 0, 0].
As we noted earlier, the documentation also displays icons to represent the
command mode(s) with which each flag is compatible.
26 CHAPTER 1 Maya Command Engine and User Interface
Python Examples
This section can be very useful for those just learning how to script with
Python or those learning how to work with Maya using Python. Here
you can find working examples of the command in use. Some example
sections can have several different samples to help you understand how
the command works. The example for the polyCube command in the docu-
ments shows you how to create a polygon cube and also how to query an
existing cube’s width.
PYTHON VERSION
One final point that is worth discussing is how to locate which version of
Python your copy of Maya is using. Python has been integrated into Maya
since version 8.5, and each new version of Maya typically integrates the
newest stable version of Python as well. Since newer versions of Python
will have new features, you may want to investigate them. First, find out
what version of Python your version of Maya is using.
1. Open up the Script Editor and execute the following lines.
import sys;
print(sys.version);
You should see a result print in the Script Editor’s History Panel that looks
something like the following lines.
2.6.4 (r264:75706, Nov 3 2009, 11:26:40)
[GCC 4.0.1 (Apple Inc. build 5493)]
CONCLUDING REMARKS
In this chapter you have learned how Maya commands and Python work
within Maya’s architecture. We have introduced a few methods of entering
Maya commands with Python to modify Maya scenes. We have also
explained how to look up help and read the Python Command Reference doc-
umentation and how to find information about your version of Python. In the
chapters that immediately follow, we will further explain some of the underly-
ing mechanics and syntax of Python and then start creating more complicated
scripts to use in Maya.
Chapter
2
Python Data Basics
CHAPTER OUTLINE
Variables and Data 30
Variables in MEL 33
Keywords 33
Python’s Data Model 34
Mutability 35
Reference Counting 36
del() 37
The None Type 37
Using Variables with Maya Commands 37
Capturing Results 39
getAttr and setAttr 40
Compound Attributes 40
connectAttr and disconnectAttr 41
Working with Numbers 43
Number Types 43
Basic Operators 44
Working with Booleans 45
Boolean and Bitwise Operators 45
Working with Sequence Types 46
Operators 46
Concatenation 47
Indexing and Slicing 47
String Types 50
Escape Sequences and Multiline Strings 50
Raw Strings 51
Unicode Strings 51
Formatting Strings 52
More on Lists 53
del() 54
Nested Lists 54
Other Container Types 56
Sets 57
Operators 57
Dictionaries 58
Operators 59
Dictionaries in Practice 60
Concluding Remarks 62
Maya Python for Games and Film. DOI: 10.1016/B978-0-12-378578-7.00002-8
© 2012 Elsevier Inc. All rights reserved. 29
30 CHAPTER 2 Python Data Basics
2. Once you create this variable, you can substitute in this name anywhere
you would like this value to appear. Execute the following line of code.
You should see the string “toys in the box” print on the next line.
print(contents+' in the box');
3. You can change the value assigned to this variable at any time, which
will substitute in the new value anywhere the name appears. Execute
the following lines of code, which should print “shoes in the box” in
the History Panel.
contents = 'shoes';
print(contents+' in the box');
4. You can also assign completely different types of values to the variable.
Execute the following line of code.
contents = 6;
Python is what is called a strong, dynamically typed language. The line of
code in step 4 demonstrates dynamic typing. You are able to change the type
of any Python variable on-the-fly, simply by changing its assignment value.
However, because it is strongly typed, you cannot simply add this new value
to a string.
5. Try to execute the following statement.
print('there are '+contents+' things in the box');
The console should supply an error message like the following one.
# Error: TypeError: file <maya console> line 1: cannot
concatenate 'str' and 'int' objects #
You should see the following line in the History Panel, which indicates
that the variable is currently pointing to an integer.
As you can see, casting the variable to a string as you did in step 7 did not
change its inherent type, but only converted the value we retrieved from the
variable. As such, you would still be able to add and subtract to and from
this variable as a number. You could also reassign a string representation to
it by assigning the recast value.
9. Execute the following lines to convert the variable to a string.
contents = str(contents);
print(type(contents));
<type 'str'>
float() Decimal number If argument is string, raises ValueError if not properly formatted
int() Integer number If argument is string, raises ValueError if not properly formatted
If argument is decimal number, result is truncated toward 0
Allows optional argument to specify non-base 10
str() String
unicode() Unicode string Allows optional argument to specify encoding
Variables and Data 33
Variables in MEL
Variables in Python are incredibly flexible. Compare the previous example
with a comparable MEL snippet.
1. Enter the following lines in a MEL tab in the Script Editor. You should
again see the output “toys in the box” in the History Panel.
$contents = "toys";
print($contents+" in the box");
While MEL allows—but does not require—that you explicitly provide the
variable’s type, the variable $contents is statically typed at this point. It is
a string, and so cannot now become a number. Those unfamiliar with MEL
should also note that it requires variable names to be prefixed with a dollar
sign ($).
2. Execute the following lines in MEL.
$contents = 6;
print("there are "+$contents+" things in the box");
Because you get the output you expect (“there are 6 things in the box”), you
may think that MEL has implicitly handled a conversion in the print call. How-
ever, the number 6 stored in $contents is not in fact a number, but is a string.
You can confirm this fact by trying to perform addition with another number.
3. Execute the following line in MEL.
print($contents+10);
Whereas the Python example printed the number 16 in this case, MEL has
printed 610! In MEL, because the type of the variable cannot change, MEL
implicitly assumed that the number 10 following the addition operator (+)
was to be converted to a string, and the two were to be concatenated. While sea-
soned MEL developers should be well aware of this phenomenon, readers who
are new to Maya will benefit from understanding this difference between MEL
and Python, as you may occasionally need or want to call statements in MEL.
On the other hand, all readers who are as yet unfamiliar with Python would
do well to remember that variable types could change on-the-fly. This
feature offers you a great deal of flexibility, but can also cause problems
if you’re frequently reusing vague, unimaginative variable names.
Keywords
Apart from issues that may arise from vague variable names, Python users
have some further restrictions on names available for use. Like any other
language, Python has a set of built-in keywords that have special meanings.
34 CHAPTER 2 Python Data Basics
import keyword;
for kw in keyword.kwlist: print(kw);
The list of reserved keywords printed out are used for various purposes,
including defining new types of objects and controlling program flow.
We will be covering a number of these keywords throughout the text, but
it is always a good idea to refer to the Python documentation if you would
like more information. The important point right now is that these words all
have special meanings, and you cannot give any of these names to your
variables.
In this case, you are not actually altering the data’s underlying type, but are
pointing to some different piece of data altogether. You can confirm this
fact by using the built-in id() function, which provides the address to the
data. For instance, printing the identity at different points in the following
short sample will show you different addresses when the variable is an inte-
ger and when it is a string.
var = 5;
print('int id',id(var));
var = str(var);
print('str id',id(var));
Mutability
In Python, objects can be either mutable or immutable. Briefly construed,
mutable objects can have their values changed (mutated), while immutable
objects cannot.2 We briefly mentioned this concept in Chapter 1 when com-
paring lists and tuples.
In fact, tuples, strings, and numbers are all immutable. As a consequence,
when you assign a new integer value to a variable, instead of changing
the underlying value of the object to which the variable is pointing, the
variable instead points to another piece of data. You can see the effects
of this concept in the following short code example, which will print the
identity for the variable after different integer assignments.
var = 5;
print('5 id',id(var));
var = 6;
print('6 id',id(var));
1
C++ programmers should note that although Python variables are references to data, they
cannot simply be used like pointers. To shoehorn Python into the language of C++, it
always passes parameters by value, but the value of a variable in Python is a reference.
The consequence is that reassigning a variable inside of a function has no effect on its
value outside the function. Chapter 9 discusses these consequences of Python’s data
model in Maya’s API.
2
Immutable containers that reference mutable objects can have their values changed if the
value of one of the mutable objects in the container changes. These containers are still
considered immutable, however, because identities to which they refer do not change.
See the “Nested Lists” section in this chapter for more information.
36 CHAPTER 2 Python Data Basics
Reference Counting
As part of its data model, Python uses a system known as reference count-
ing to manage its memory. The basic idea is that rather than requiring
developers to manually allocate and deallocate memory, data are garbage
collected when there are no more names referencing them.
An interesting side effect of this paradigm is that two immutable variables
with the same assignment (e.g., data with the same type and value) may in
fact be pointing to the same data in memory (Figure 2.1). You can see this
principle in action by assigning the same numeric value to two different
variables and printing their identities.
v1 = 10;
v2 = 10;
print('v1 id', id(v1));
print('v2 id', id(v2));
In this case, both v1 and v2 are pointing to the same piece of data. If these
two variables are assigned different data (e.g., some other number, a string,
etc.), then the reference count for their previous data (the integer 10) drops
to zero. When the reference count for objects drops to zero, Python nor-
mally automatically garbage collects the data to free up memory as needed.
Although this concept has only a few consequences for our current discus-
sion, it becomes more important in later chapters as we discuss modules,
classes, and using the API.
It is important to note that while variables pointing to data with an immu-
table type may show this behavior, two separate assignments to mutable
objects with the same type and value are always guaranteed to be different.
For example, even though the following lists contain the same items, they
will be guaranteed to have unique identities.
Using Variables with Maya Commands 37
del()
Python has a built-in function, del(), which allows you to delete variables.
Note that this process is not the same as deleting the data referenced by the
variable: Python’s garbage collector will still manage those data. Using this
function with a variable name simply clears the name (and thus eliminates a
reference to its data). The following example illustrates that, even though
v1 and v2 will reference the same data, deleting v1 has no effect on v2.
Trying to access v1 after this point would result in a NameError.
v1 = 5;
v2 = 5;
del(v1);
print(v2);
Recall that the results of the polySphere command return a list of object
names (a transform node and a shape node). You can store this result in
a variable when you create a cube. The sphereNodes list now contains
the names of the two objects that were created. If you were to print this list,
you would see something like the following line.
[u'pSphere1', u'polySphere1']
Note that this list does not contain the Maya nodes themselves, but simply
contains their names. For example, using the del() function on this list
would not actually delete Maya nodes, but would simply delete a list with
two strings in it.
2. We will discuss this syntax later in this chapter, but you can use square
bracket characters to access items in this list. For example, you can store
the name of the polySphere node (“polySphere1”) in another variable.
sphereShape = sphereNodes[1];
3. Now that you have stored the name of the shape in a variable, you can
use the variable in conjunction with the polySphere command to query
and edit values. For example, the following lines will store the sphere’s
radius in a variable, and then multiply the sphere’s radius by 2. Remem-
ber that in each flag argument, the first name is the flag, and the second
name is the value for the flag.
rad = maya.cmds.polySphere(
sphereShape, q=True, radius=True
);
maya.cmds.polySphere(sphereShape, e=True, radius=rad*2);
4. You could now reread the radius attribute from the sphere and store it
in a variable to create a cube the same size as your sphere.
Using Variables with Maya Commands 39
rad = maya.cmds.polySphere(
sphereShape, q=True, radius=True
);
maya.cmds.polyCube(
width=rad*2,
height=rad*2,
depth=rad*2
);
Hopefully you see just how easy it is to use variables in conjunction with
Maya commands.
Capturing Results
In practice, it is critical that you always capture the results of your commands
in variables rather than making assumptions about the current state of your
nodes’ attributes. For example, Maya will sometimes perform validation
on your data, such as automatically renaming nodes to avoid conflicts.
Some Maya users may insist that this behavior makes certain tools impos-
sible without advanced, object-oriented programming techniques. In reality,
you simply need to take care that you use variables to store your com-
mands’ results, and do not simply insert literal values—especially object
names—into your code. The following example illustrates this point.
1. Create a new Maya scene and execute the following lines in the Script
Editor. This code will create a sphere named “head.”
import maya.cmds;
maya.cmds.polySphere(name='head');
2. Now execute the following line to try to make a cube with the same name.
maya.cmds.polyCube(name='head');
If you actually look at your cube in the scene, you can see that Maya has
automatically renamed it to “head1” so it will not conflict with the name
you gave the sphere. However, if you were writing a standalone tool that
creates objects with specific names and then tries to use those specific
names, your artists may run into problems if they already have objects in
the scene with conflicting names.
3. Try to execute the following line, and you will get an error.
maya.cmds.polyCube('head', q=True, height=True);
Always remember that Maya commands work with nodes and attributes on
the basis of their names, which are simply strings. When using ordinary
Maya commands, you should always capture the results of your commands
40 CHAPTER 2 Python Data Basics
The getAttr command allows you to get the value of any attribute on any
node by simply passing in a string with the node’s name, a period, and the
attribute name. We’ll talk more about working with strings shortly, but the
complete string that we passed to the getAttr command was actually “loca-
tor1.scaleX” in this case.
3. Execute the following lines to double the sx value and assign the new
value to the node’s attribute.
sx *= 2;
maya.cmds.setAttr(loc+'.scaleX', sx);
The setAttr command works just like the getAttr command, and allows
you to set any attribute value on any node by passing a string with the
node’s name, a period, and the attribute name.
Compound Attributes
Many attributes will simply be a string, a Boolean, or a number value.
However, some attributes are called compound attributes, and may contain
several values. It is important to note that these attribute types work differ-
ently with the getAttr and setAttr commands compared to other built-in
commands.
Using Variables with Maya Commands 41
The reason for this difference is that the getAttr and setAttr commands do
not know what data type the particular attribute expects or contains until they
look it up by name. Other commands only work with specific attributes on
specific nodes, and so can work in a more straightforward way, as you will
see in the remainder of this example.
4. In the scene you created in the previous steps, execute the following
line to print the locator’s translation using the xform command.
print(maya.cmds.xform(loc, q=True, translation=True));
As you would expect the result is simply a list: [0.0, 0.0, 0.0].
5. Likewise, when using the xform command, you can set a new translation
value using a list, as in the following line.
maya.cmds.xform(loc, translation=[0,1,0]);
The xform command can work in this way because it is designed to work
exclusively with transform nodes, and the command internally knows
about the data type for the appropriate attribute. On the other hand,
getAttr and setAttr are not so straightforward.
6. Execute the following line to print the locator’s translation using the
getAttr command.
print(maya.cmds.getAttr(loc+'.translate'));
As you can see from the output, the command returns a list that contains
a tuple: [(0.0, 1.0, 0.0)].
7. Using setAttr for a compound attribute also uses a different paradigm.
Execute the following line to set a new translation value for the locator.
maya.cmds.setAttr(loc+'.translate', 1, 2, 3);
As you can see, setting a compound attribute like translation using setAttr
requires that you specify each value in order (x, y, z in this case).
attribute. However, Maya does perform some built-in conversions for you
automatically, such as converting angle values into decimal numbers. The finer
distinctions between these types of values will be clearer when we discuss the
API later in this book. In the following short example, you will create a basic
connection to control one object’s translation with another object’s rotation.
1. Open a new Maya scene and execute the following lines to create a
sphere and a cube and store the names of their transform nodes.
import maya.cmds;
sphere = maya.cmds.polySphere()[0];
cube = maya.cmds.polyCube()[0];
Use the Rotate tool (E) to rotate the cube around its y-axis and observe the
behavior. The result is very dramatic! Because you are mapping a rotation
in degrees to a linear translation, small rotations of the cube result in large
translations in the sphere.
It is also worth mentioning that the connection is only one way. You cannot
translate the sphere to rotate the cube. In Maya, without some very compli-
cated hacks, connections can only flow in one direction. Note, too, that an
output attribute can be connected to as many inputs as you like, but an
input attribute can only have a single incoming connection.
3. Execute the following line to disconnect the two attributes you just
connected.
maya.cmds.disconnectAttr(cube+'.ry', sphere+'.ty');
Now if you rotate the cube, the sphere translates 1 unit for every 90 degrees
of rotation.
Working with Numbers 43
Number Types
Although you can often intermix different types of numbers in Python,
there are four types of numbers: integers, long integers, floating-point num-
bers, and complex numbers. We briefly cover them here, but you can read
more about these different types in Section 5.4 of Python Standard Library.
As you saw in the beginning of this chapter, an integer is simply a whole
(nonfractional) number. Integers can be positive or negative. The type of
an integer in Python is given as int, as the following code illustrates.
var = -5;
print(type(var));
A long integer differs from an integer only in that it occupies more space in
memory. In many cases, ordinary integers suffice and are more efficient, but
long integers may be useful for computation that deals with large numbers.
In a language like C or C++, a long integer occupies twice as many bits in
memory as an ordinary integer. In Python, a long integer can occupy as
much memory as you require. To create a long integer, you can simply
assign a really long value to your variable and it will become a long integer
automatically, or you can suffix the value with the character l or L. The type
in Python is given as long.
var = -5L;
print(type(var));
Finally, Python allows you to use complex numbers, which consist of both a
real and an imaginary component. It is highly unlikely that you will need to
work with complex numbers regularly. You can create a complex number by
44 CHAPTER 2 Python Data Basics
suffixing the imaginary part with the character j or J. The type is given as
complex.
var = -5+2j;
print(type(var));
You can also access the individual real and imaginary parts of complex
numbers using the real and imag attributes.
print(var.real, var.imag);
Basic Operators
Once you start creating variables, you will want to do things with them.
Operators are special symbols you can include in your code to perform spe-
cial functions. (Note that we also include some related built-in functions and
object methods in our tables.) Section 5 of Python Standard Library includes
information on various operators, and Section 3.4 of Python Language
Reference contains information on overloading operators, which allows
you to assign special functionality to these symbols. Here, we briefly review
some of the basic operators for working with numeric values.
Thus far, you’ve seen some of the basic math operators, such as + for addition
and – for subtraction or negation. Section 5.4 in Python Standard Library con-
tains a table of Python’s built-in operators for working with numeric types.
In Table 2.2 we have recreated the parts of this table containing the most
common operators.
Note that many of these operators also allow in-place operations when used
in conjunction with the assignment operator (=). For example, the following
lines create a variable, v1, with a value of 2, and then subtracts 4 from the
same variable, resulting in −2.
v1 = 2;
v1 -= 4;
print(v1);
Note that Python does not support incremental operators such as ++ and −−.
For those readers who are new to programming, it is important to point out
how division works with integer numbers. Remember that integers are
whole numbers. Consequently, the result is always rounded down. The fol-
lowing floating-point division results in 0.5.
1.0/2.0;
You can also mix an integer and a floating-point number, in which case
both are treated as floats. The following division results in 0.5.
1.0/2;
It is also worth mentioning, for those unacquainted with the finer points of
computer arithmetic, that floating-point operations often result in minor
precision errors as a consequence of how they are represented internally.
It is not uncommon to see an infinitesimally small number where you might
actually expect zero. These numbers are given in scientific notation, such as
the following example.
-1.20552649145e-10
Operators
As with numbers and Booleans, sequence types have a set of operators that
allow you to work with them conveniently. Section 5.6 of Python Standard
Library has a table of operations usable with sequence types. We have
selected the most common of these operations to display in Table 2.4.
Because they are perhaps not as immediately obvious as math operators,
some merit a bit of discussion.
3
It is also worth noting that the bitwise inversion operator (~) is not equivalent to the Boolean
not operator when working with Boolean variables. Booleans are not simply 1-bit values, but
are built on top of integers. Consequently, ~False is −1 and ~True is −2.
Working with Sequence Types 47
Concatenation
The first operator worthy of a little discussion is the concatenation operator
(+). As you saw in the examples at the outset of this chapter, MEL concate-
nated two strings that we expected to be numbers. Python allows sequence
concatenation in the same way. Concatenation creates a new sequence com-
posed of all of the elements of the first sequence, followed by all of the ele-
ments in the second sequence. You can concatenate any sequence types, but
only with other sequences of the same type. You cannot concatenate a list with
a tuple, for instance.
The following line produces the string “Words make sentences.”
'Words' + ' ' + 'make' + ' ' + 'sentences.';
string value: a b c d e
indices: 0 1 2 3 4
tuple elements: 1 2 3 4 5
negative indices: -5 -4 -3 -2 -1
string value: H o l y c a t s , P y t h o n i s a w e s o m e
indices: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
'abcde'[2];
Because lists are mutable, you can also use this operator to set individual
values for a list. The following line would result in the list [0, 2, 3].
[1,2,3][0] = 0;
However, because they are immutable, you cannot use the index operator to
change individual items in a tuple or characters in a string. The following
two lines would fail.
'abcde'[2] = 'C';
(1,2,3)[0] = 0;
You can use a series of index operators to access elements from sequences
embedded in sequences. For instance, the following example will extract
just the “x” character.
('another', 'example')[1][1];
Python’s index operator also offers powerful, concise syntax for generating
slices from sequences. You can think of a slice as a chunk extracted from a
sequence. The most basic syntax for a slice includes two numbers inside
the square brackets, separated by a colon. The first number represents the
start index, and the second number represents the end index of the slice
(Figure 2.4). Consider the following example.
Working with Sequence Types 49
You could print just the word “cats” using the following slice. Note that the
letter “s” itself is index 8.
print(var[5:9]);
As you can see, the end index for the slice is the index just beyond the last
element you want to include.
Slicing syntax assumes that you want to start at index 0 if the first number
is not specified. You could print “Holy cats” with the following slice.
print(var[:9]);
If you omit the second number, or if it is greater than the sequence’s length,
it is assumed to be equal to the sequence’s length. You could print just the
word “awesome” using the following snippet. The start index is specified
using a negative number based on the length of the word “awesome” at
the end of the string.
print(var[-len('awesome'):]);
Or you could print the string “Python is awesome” using the following line.
The start index is specified using the index() method, which returns the
index of the first occurrence in the sequence of the item you specify.
print(var[var.index('Python'):]);
Slicing syntax also offers the option of providing a third colon-delimited num-
ber inside the square brackets. This third number represents the step count for
a slice, and defaults to 1 if it is left empty. Consider the following variable.
nums = (1, 2, 3, 4, 5, 6, 7, 8);
The following line would return a tuple containing the first four numbers,
(1, 2, 3, 4).
nums[:4:];
Specifying a skip value would allow you to return a tuple containing all of
the odd numbers, (1, 3, 5, 7).
nums[::2];
Specifying a skip value and a start index would return a tuple with all of the
even numbers, (2, 4, 6, 8).
nums[1::2];
You can also specify a negative number to reverse the sequence! For
instance, the following line would return the tuple (8, 7, 6, 5, 4, 3, 2, 1).
nums[::-1];
50 CHAPTER 2 Python Data Basics
String Types
As with numbers, there are in fact multiple string types, which Maya com-
mands allow you to use interchangeably. Recall that a string is a sequence
of numbers or characters inside of quotation marks that is treated as though
it were a word. However, Python also allows you to prefix strings with spe-
cial characters to create raw and Unicode strings. Each of these requires
that we first introduce you to escape sequences.
Similarly, if you wanted to include a line break, you would use one of the
following three examples. (Note that we omit semicolons at line endings
here for demonstration, since we can assume this sample is short enough
to print correctly.)
var = 'line 1\nline 2'
var = "line 1\nline 2"
var = """line 1
line 2"""
If you were to print var, each of these three examples would produce the
same result.
line 1
line 2
Note that using a pair of triple quotation marks allows you to span multiple
lines, where your return carriage is contained in the literal value. Recall that
we mentioned in the introduction that Python also lets you use a backslash
character at the end of the line to carry long statements onto a new line.
Working with Sequence Types 51
However, this pattern does not translate into a literal return carriage.
Consider the following lines.
var = 'line 1 \
line 2'
Raw Strings
Python supports what are called raw strings. A raw string, though still a
string according to its underlying type, allows you to include backslashes
without escaping them. You can include the r or R character prefix for your
value to indicate that the value is a raw string, and that backslashes should
not be presumed to escape the following character. The following two exam-
ples produce the same result.
var = 'C:\\Users\\Adam\\Desktop';
var = r'C:\Users\Adam\Desktop';
Raw strings can be helpful when creating directory paths or regular expres-
sions. Regular expressions are special patterns that allow you to search
string data for particular sequences. While they are invaluable, they are also
complex enough that they merit entire books on their own, so we do not
cover them here. Consult the companion web site for some tips on using
regular expressions in Maya.
Unicode Strings
A Unicode string allows you to handle special characters, irrespective of region
encoding. For example, with ordinary strings, each character is represented
internally with an 8-bit number, allowing for 256 different possibilities. Unfor-
tunately, while 256 characters may suffice for any one language, they are insuf-
ficient to represent a set of characters across multiple languages (e.g., Roman
characters, Korean, Japanese, Chinese, Arabic). You can create a Unicode
string by prefixing the character u or U onto the value. Their type is Unicode.
var = u'-5';
print(type(var));
Unicode strings benefit from most of the same operators and functions
available to ordinary strings. Section 5.6.1 of Python Standard Library lists
a variety of useful built-in methods for strings. We strongly recommend
browsing these built-in methods, because there are a number of incredibly
useful ones that will save you loads of time when working in Maya. You
can also pull up a list of string methods directly in your interpreter by
calling the built-in help() function.
help(str);
You may have also noticed that Maya returns object names as Unicode
characters when you execute commands. For example, if you create a
new cube and print the result, the History Panel shows you a list of
Unicode strings. You can verify this by printing the result of the polyCube
command.
import maya.cmds;
print(maya.cmds.polyCube());
Formatting Strings
While MEL users will feel right at home simply concatenating strings, this
approach can quickly become verbose and inefficient. For instance, the fol-
lowing example would print the string “There are 6 sides to a cube, and
about 6.283185308 radians in a circle.”
cube = 6;
pi = 3.141592654;
print(
'There are '+str(cube)+
' sides to a cube, and about '+
str(2*pi)+' radians in a circle.'
);
Apart from the tedium of casting your variables as strings, the value of 2π
is unnecessarily verbose for human-readable output.
Fortunately, strings and Unicode strings in Python allow you to use
powerful, concise formatting operations to increase efficiency, reduce
verbosity, and alter the appearance of output. The basic approach is that
you insert a % character in the string to initiate a formatting sequence,
and then follow the string’s value with another % character and a list
of the arguments in order. The previous example could be rewritten in
the following way.
Working with Sequence Types 53
cube = 6;
pi = 3.141592654;
print(
'There are %s sides to a cube, and about %.2f radians in a
circle'%(
cube, 2*pi
)
);
Using this formatting process, the result is now “There are 6 sides to a
cube, and about 6.28 radians in a circle.”
Section 5.6.2 of Python Standard Library provides information on more
detailed options for string formatting, though we only use this basic paradigm
throughout the book. The documentation also contains a list of available string
formatting codes. We have listed some common patterns in Table 2.5.
The Python documentation also lists other flags that can accompany some of
these codes. Though you should refer to Python’s documents for more infor-
mation, it is worth describing the precision modifier, as we use it occasionally.
Note that you can modify the precision that a decimal number will use by
following the % character in the string with a period and number, before
the formatting character. For example, the following lines create a variable
pi and print it to five decimal places.
pi = 3.141592654;
print('%.5f'%pi);
More on Lists
Because lists are mutable, they have some properties not shared with other
sequence types. For instance, as you have already seen, lists alone allow for
individual element assignment using the index operator. However, lists
have a couple of other unique properties worth briefly discussing.
Discovering Diverse Content Through
Random Scribd Documents
Unsere Fabrik war die wahrhafte Verkörperung dieser Umwälzung.
Etliche Mal im Monat wurde aus der zunächstgelegenen chemischen
Fabrik auf dem Schienenweg für die Spinnerei „Material“ geliefert,
das heißt: eine durchsichtige Flüssigkeit in gewaltigen Zisternen. Aus
diesen Zisternen wurde vermittels besonderer luftdichter Apparate
das Material in ungeheure, hohe Metallreservoire geleitet, deren
dichter Boden hunderttausend mikroskopisch kleine Oeffnungen
besaß. Durch diese Oeffnungen gelangte die klebrige Flüssigkeit
unter einen starken Luftdruck und verhärtete sich zu zähen Fasern.
Zehntausend mechanische Spindeln erfaßten diese Fasern, spannen
sie zu Fäden verschiedener Dicke, schafften das Gespinst in die
Webeabteilung. Hier wurden die verschiedenen Stoffe gewebt, von
den allerfeinsten, wie Musselin und Batist, bis zu den dicksten, wie
Tuch und Filz. Die endlosen breiten Streifen gelangten nun weiter in
die Zuschneidewerkstätte. Hier wurden sie von neuen Maschinen
gepackt, sorgfältig gefaltet, geschichtet, zu genau ausgemessenen
Stücken zerschnitten, zu Stücken, die die einzelnen Teile des
Gewandes bildeten.
In der Schneiderwerkstatt wurden aus den zugeschnittenen
Stücken fertige Kleider hergestellt, jedoch ohne daß dabei Nadel,
Faden oder Nähmaschine angewandt worden wären. Durch einen
chemischen Prozeß wurden die Ränder der Kleidungsstücke erweicht
und abermals in ihren ersten flüssigen Zustand versetzt. Sobald die
chemische Substanz verdunstete, waren die Kleider gleichsam
zusammengelötet, fester, als es bei der besten Schneiderarbeit der
Fall gewesen wäre. Diese Lötung wurde gleichzeitig überall
vollzogen, wo es nottat, so daß auf diese Art fertige Kleider
hergestellt wurden, und zwar in einigen tausend Mustern, der Form
und dem Maß nach verschieden.
Es gab für jede Größe einige hundert Muster, aus denen ein jeder
fast immer das geeignete zu wählen vermochte, und dies umso
mehr, als sich die Marsbewohner äußerst ungezwungen kleideten.
War dennoch das Geeignete nicht vorhanden, wie etwa im Fall einer
körperlichen Unnormalität, so kam das Stück abermals unter die
Zuschneidemaschine; es wurde ein besonderer Anzug „genäht“, was
etwa eine Stunde in Anspruch nahm.
Was die Farbe der Gewänder anbelangte, so trugen die
Marsbewohner meist dunkle weiche Farben, die dem Material
entsprachen. Wurde jedoch eine andere Farbe verlangt, so kam der
Anzug in die Färbeabteilung und erhielt vermittels eines chemisch-
elektrischen Prozesses die gewünschte Farbe, die ideal gleichmäßig
und ideal dauerhaft war.
Aus den gleichen, nur viel dickeren Geweben wurden das
Schuhwerk und die warmen Winterkleider hergestellt. Unsere Fabrik
verfertigte diese nicht, doch gab es andere, noch größere Betriebe,
in denen alles verfertigt wurde, was ein Mensch vom Kopf bis zu den
Füßen an Bekleidung braucht.
Ich arbeitete der Reihe nach in allen Abteilungen des Betriebes,
ließ mich anfangs völlig von meiner Arbeit hinreißen. Besonders
interessant erschien mir die Zuschneidewerkstatt; hier mußte ich bei
meiner Arbeit mir bisher unbekannte Hilfsmittel in Anspruch
nehmen: die mathematische Analyse. Die Aufgabe bestand darin,
aus einem gegebenen Stück bei dem geringstmöglichen
Materialverlust alle Teile eines Anzugs zu gewinnen. Dies war
natürlich eine äußerst prosaische, aber auch ernste Sache, denn
selbst der geringste Irrtum, der sich im Verlauf der Arbeit viele
Millionen Mal wiederholte, bedeutete einen ungeheuren Verlust.
Einen erfolgreichen Entschluß zu fassen, gelang mir meist „nicht
schlechter“ als andern.
Nicht „schlechter“ zu arbeiten als die anderen, das strebte ich aus
allen Kräften an, und fast immer mit einem gewissen Erfolg. Doch
mußte ich bemerken, daß dies für mich eine weit größere
Anstrengung bedeutete als für meine Kameraden. Nach den
gewöhnlichen vier bis sechs Arbeitsstunden – die Erdenberechnung
als Grundlage genommen – fühlte ich heftige Erschöpfung und
mußte sofort rasten, während die andern noch in Museen,
Bibliotheken, Laboratorien gingen oder aber in andere Fabriken, um
dort die Arbeit zu beobachten, bisweilen auch noch selbst
mitzuarbeiten ...
Ich hoffte, mich allmählich an die neue Arbeit zu gewöhnen und
meinen Genossen gleich zu werden. Doch geschah dies nicht. Ich
überzeugte mich immer mehr davon, daß mir die Kultur der
Aufmerksamkeit fehle. Körperliche Bewegungen wurden äußerst
wenig erfordert, und was deren Schnelligkeit und Gewandtheit
anbelangte, so stand ich nicht hinter den anderen zurück, ja, ich
übertraf sie sogar. Aber die ununterbrochene aufmerksame
Beobachtung der Maschine und des Materials fiel meinem Gehirn
ungeheuer schwer: diese Fähigkeit vermag sich offensichtlich erst im
Verlauf einiger Generationen zu jener Stufe zu entwickeln, die hier
als Durchschnitt und völlig alltäglich erscheint.
Wenn mich, und dies war meist am Ende des Arbeitstages der Fall,
Erschöpfung ankam und meine Aufmerksamkeit nachließ, ich Fehler
beging oder auf eine Sekunde die Ausführung einer Arbeit unterließ,
brachte die unermüdliche, unbeirrte Hand meines Nachbarn die
Sache immer in Ordnung.
Die merkwürdige Fähigkeit dieser Menschen, alles ringsum zu
beobachten, ohne dabei auch nur im geringsten die eigene Arbeit zu
vernachlässigen, versetzte mich in Erstaunen und reizte mich sogar.
Ihre Fürsorge störte mich nicht nur, nein, sie rief in mir auch Aerger
und Ungeduld wach; erregte in mir das Gefühl, als ob alle
ununterbrochen meine Tätigkeit verfolgten ... Diese Unruhe
verstärkte noch meine Zerstreutheit und ließ mich schlechter
arbeiten.
Heute, nach langer Zeit, da ich genau und leidenschaftslos an all
dies zurückdenke, sehe ich ein, daß ich es damals falsch aufgefaßt
habe. Mit der gleichen Fürsorge und auf dieselbe Art halfen meine
Genossen in der Fabrik einander. Ich war keineswegs der
Gegenstand irgendeiner ausschließlichen Aufsicht oder Kontrolle, wie
es mich damals dünkte. Ich selbst, der Mensch aus einer
individualistischen Welt, sonderte mich von den übrigen ab und
verkannte auf krankhafte Art ihre Güte und ihre kameradschaftlichen
Dienste, für die sie, die Menschen einer kameradschaftlichen Welt,
von mir nicht gewürdigt werden konnten.
Enno
Enno war seit ihrer frühesten Jugend mit Netti befreundet gewesen
und wußte mir über sie viel zu erzählen. Während eines unserer
Gespräche wurden Nettis und Sternis Namen in einer gewissen
Verbindung genannt, die mir merkwürdig erschien. Als ich darauf
eine direkte Frage stellte, überlegte Enno eine Weile, wurde schier
verwirrt und erwiderte schließlich:
„Netti war früher Sternis Frau. Wenn sie Ihnen dies nicht gesagt
hat, so steht mir kein Recht zu, darüber zu reden. Ich beging
offensichtlich einen Irrtum und Sie dürfen mich nicht weiter
befragen.“
Das Vernommene erschütterte mich seltsam ... Eigentlich war es
ja nichts Neues, Unerwartetes ... Ich hatte niemals angenommen,
daß ich Nettis erster Mann sei. Es wäre Torheit gewesen, zu glauben,
daß eine lebensvolle, gesunde Frau mit schönem Leib und schöner
Seele, das Kind einer freien, hochkultivierten Rasse, bis zu unserer
Begegnung ohne Liebe gelebt habe. Weshalb also meine
unbegreifliche Verblüffung? Ich vermochte keine Erklärung dafür zu
finden, kannte bloß ein Gefühl: ich müsse alles erfahren, alles genau
und klar wissen. Enno zu befragen, ging offensichtlich nicht an. Ich
erinnerte mich an Nella.
Netti hatte vor ihrer Abfahrt zu mir gesprochen: „Vergiß Nella
nicht; suche sie auf in deinen schweren Augenblicken.“ Ich hatte
schon mehr als einmal daran gedacht, zu Nella zu gehen, war aber
zum Teil durch meine Arbeit, zum Teil durch die unklare Angst vor
den Hunderten von neugierigen Kinderaugen zurückgehalten
worden. Jetzt jedoch schwand jegliche Unentschlossenheit; noch am
gleichen Tag begab ich mich nach dem Haus der Kinder, in die große
Maschinenstadt.
Nella ließ sogleich ihre Arbeit liegen, bat eine der Erzieherinnen,
sie zu vertreten und führte mich in ihre Stube, wo uns die Kinder
nicht stören würden.
Ich beschloß, ihr nicht sofort den Zweck meines Besuches zu
bekennen, umsomehr, als mir dieser Zweck auch selbst nicht recht
vernünftig und ganz richtig erschien. Es war ja vollkommen
natürlich, daß ich das Gespräch auf jenes Wesen lenkte, das uns
beiden das teuerste war, und dann den günstigsten Augenblick für
meine Frage abwartete. Nella erzählte voller Eifer von Netti, deren
Kindheit und Jugend.
Ihre ersten Lebensjahre hatte Netti bei der Mutter verbracht, wie
dies auf dem Mars allgemein üblich war. Als dann die Zeit kam, da
Netti ins Haus der Kinder gebracht werden mußte, damit sie nicht
den erzieherischen Einfluß des Umgangs mit anderen Kindern
entbehre, brachte es Nella nicht übers Herz, sich schon von ihr zu
trennen und lebte mit ihr zusammen in dieser Anstalt, wo sie dann
schließlich als Erzieherin blieb. Das ergab sich zum Teil aus ihrem
Spezialstudium: sie hatte sich vornehmlich mit Psychologie befaßt.
Netti war ein lebhaftes, energisches, wildes Kind mit großem
Wissens- und Tatendurst. Am meisten interessierte und zog sie die
geheimnisvolle astronomische Welt jenseits des Planeten an. Die
Erde, die zu erreichen damals noch nicht gelungen war, und deren
unbekannte Menschheit waren Nettis Lieblingstraum, das
Hauptthema ihrer Gespräche mit den anderen Kindern und den
Erwachsenen.
Als der Bericht über Mennis erste erfolgreiche Expedition nach der
Erde veröffentlicht wurde, verlor das kleine Mädchen vor Freude und
Entzücken fast den Verstand. Die kleine Netti kannte Mennis Bericht
Wort für Wort auswendig und quälte die Mutter sowie die
Erzieherinnen ewig mit Fragen über die ihr unverständlichen
technischen Ausdrücke, die in dem Bericht vorkamen. Netti verliebte
sich in Menni, ohne ihn zu kennen, schrieb ihm einen begeisterten
Brief, flehte ihn unter anderem an, er möge sie zu den Erdenkindern
bringen, denen keine Erziehung zu Teil werde, sie übernehme es,
diese auf vortreffliche Art zu erziehen. Sie schmückte ihr Zimmer mit
Erdenbildern und den Porträts der Erdenmenschen und stürzte sich
auf das Studium der Erdensprachen, sobald die dazu nötigen Bücher
erschienen waren. Sie entrüstete sich über die Gewalt, mit der Menni
und dessen Gefährten dem ersten Erdenmenschen begegnet waren:
sie hatten ihn gefangen genommen, damit er ihnen beim Erlernen
der Erdensprachen behilflich sei; zur gleichen Zeit jedoch bedauerte
sie heftig, daß Menni und die seinen bei der Rückkehr in die Heimat
den Erdenmenschen freigelassen und nicht nach dem Mars
mitgenommen hatten. Sie faßte den festen Entschluß, eines Tages
nach der Erde zu fliegen, und auf die Scherze der Mutter, sie würde
sich dort sicher mit einem Erdenmenschen verheiraten, entgegnete
sie sinnend: „Das ist sehr möglich.“
All diese Dinge hatte mir Netti niemals erzählt; in ihren
Gesprächen schien sie vielmehr der Vergangenheit auszuweichen.
Selbstverständlich konnte niemand, nicht einmal sie selbst, jene
Dinge besser berichten, als Nella. Bisweilen vergaß ich völlig meine
Person, sah vor mir das reizende kleine Mädchen mit den großen
funkelnden Augen und der rätselhaften Sehnsucht nach der fernen,
fernen Welt ... Doch verging diese Stimmung rasch, das Bewußtsein
meiner Umgebung kehrte zurück und damit auch die Erinnerung an
den Zweck unseres Gesprächs; von neuem drang eisige Kälte in
meine Seele.
Als sich das Gespräch den letzten Jahren aus Nettis Leben
zuwandte, beschloß ich, meine Frage zu stellen, mich so ruhig und
ungezwungen wie nur möglich nach Nettis und Sternis Verhältnis zu
erkundigen. Nella dachte einen Augenblick lang nach.
„Also deshalb suchten Sie mich auf! ... Weshalb sagten Sie es
nicht gerade heraus?“
Unerbittliche Strenge klang aus ihrer Stimme. Ich schwieg.
„Selbstverständlich kann ich es Ihnen erzählen“, fuhr sie fort. „Es
ist eine ganz einfache Geschichte. Sterni war einer von Nettis
Lehrern. Er hielt den Jüngeren Vorträge über Mathematik und
Astronomie. Als er von seiner ersten Expedition nach der Erde
zurückkehrte, – ich glaube, dies war Mennis zweite Expedition, –
hielt er eine Reihe Vorträge über diesen Planeten und dessen
Bewohner. Netti zählte zu seinen ständigen Hörern. Die Geduld und
Aufmerksamkeit, mit der er ihren ewigen Fragen begegnete, brachte
die beiden einander näher. Schließlich führte all dies zu ihrer
Verbindung. Beide waren grundverschiedene Charaktere. Das
Ergebnis der Verschiedenheit zeigte sich bald auch in ihrem
Privatleben, führte zur Entfremdung und schließlich zum Bruch. Das
ist alles.“
„Sagen Sie mir, wann kam es zum Bruch?“
„Zum endgültigen Bruch kam es nach Lettas Tode. Die innige
Freundschaft zwischen Netti und Letta gab dazu den ersten Anstoß.
Netti litt unter Sternis analytisch kaltem Verstand; er zerstörte allzu
systematisch und hartnäckig alle Luftschlösser, alle Phantasien des
Geistes und des Gefühls, die für sie einen Teil des Lebens bedeuten.
Unwillkürlich suchte sie nach einem Menschen, der sich diesen
Dingen gegenüber anders verhielt. Und dem alten Letta eigneten ein
selten teilnahmsvolles Herz sowie ein schier kindlicher Enthusiasmus.
Netti suchte in ihm jenen Gefährten, dessen sie bedurfte: Letta hatte
mit ihren Phantasien nicht nur Geduld, sondern ließ sich auch häufig
selbst von ihnen fortreißen. Bei ihm konnte sie von der strengen
selbstzerfleischenden Kritik Sternis Erholung finden. Letta liebte
gleich ihr die Erdenträume und Phantasien, glaubte an die künftige
Verbindung der beiden Welten, die eine herrliche Blüte und eine
gewaltige Lebenspoesie zur Folge haben würde. Als dann Netti
erfuhr, daß ein Mensch, in dessen Seele derartige Gefühle verborgen
lagen, niemals Frauenliebe und Zärtlichkeit kennen gelernt habe,
konnte sie sich damit nicht abfinden. Auf diese Art kam Nettis
zweiter Bund zustande.“
„Einen Augenblick“, unterbrach ich sie. „Verstehe ich Sie recht, Sie
sagten, Netti sei Lettas Frau gewesen?“
„Ja“, erwiderte Nella.
„Sie sagten aber doch, daß der endgültige Bruch mit Sterni erst
nach Lettas Tode erfolgte.“
„Ja; erscheint Ihnen dies unbegreiflich?“
„Nein, ich verstehe Sie, wußte bloß nicht darum.“
In diesem Augenblick wurde unser Gespräch unterbrochen. Eines
der Kinder hatte einen nervösen Anfall erlitten und einer der Schüler
rief Nella. Ich blieb eine Zeitlang allein. Die Gedanken wirbelten
durch meinen Kopf; mir war so seltsam zumute, daß ich dies in
Worten nicht auszudrücken vermag. Weshalb eigentlich? Es war
doch nichts Besonderes vorgefallen. Netti war ein freier Mensch,
hatte als freier Mensch gehandelt. Letta ist ihr Mann gewesen? Ich
hatte ihn stets verehrt, für ihn warme Zuneigung empfunden, hätte
ihn selbst dann geliebt, wenn er sich nicht für mich geopfert haben
würde. Netti war also gleichzeitig mit zwei Genossen verheiratet
gewesen? Ich hatte immer gefunden, daß die Monogamie in unserer
Welt ausschließlich den wirtschaftlichen Bedingungen entspringe, die
den Menschen bei jedem Schritt begrenzen und hemmen. Hier
existierten diese Bedingungen nicht, auf dem Mars herrschten
andere Verhältnisse, die dem persönlichen Gefühl und den
persönlichen Verbindungen keine Fesseln anlegten. Woher kam aber
meine Erregung und der unbegreifliche Schmerz, über den ich
aufschreien, dann aber wieder lachen hätte mögen? Konnte ich das,
was ich dachte, nicht auch fühlen? Anscheinend nicht. Und mein
eigenes Verhältnis zu Enno? Wo blieb da meine Logik? Und was bin
ich eigentlich? Welch törichte Stimmung!
Ach ja, und auch dies berührte mich peinlich: weshalb hatte Netti
nicht mit mir darüber gesprochen? Wie viele Geheimnisse, wie viel
Betrug umgeben mich noch? Wie viele harren meiner in der Zukunft?
Aber nein, auch dies stimmt nicht! Geheimnisse, ja, aber kein
Betrug. Ist aber nicht auch schon das Geheimnis ein Betrug?
Derartige Gedanken wirbelten durch meinen Kopf, als sich die Tür
öffnete und Nella zurückkam. Sie las augenscheinlich von meinen
Zügen ab, wie schwer mir ums Herz war, denn der Ton, mit dem sie
sich an mich wandte, war frei von Strenge und Kälte.
„Es ist natürlich schwer“, meinte sie, „sich an die völlig fremden
Lebensbedingungen und an die Sitten einer anderen Welt zu
gewöhnen, mit der Sie keine Blutsverwandtschaft verbindet. Sie
haben bereits in dieser Beziehung manchen Sieg errungen, finden
Sie sich nun auch in diese Dinge. Netti glaubt an Sie, und mir
scheint, daß sie recht hat. Ist etwa Ihr Vertrauen zu Netti, Ihr Glaube
an sie schwankend geworden?“
„Weshalb verbarg sie diese Tatsache vor mir? Wo blieb da ihr
Glaube? Ich begreife sie nicht.“
„Ich weiß nicht, weshalb sie so handelte. Doch bin ich davon
überzeugt, daß sie hierfür gewichtige und edle Gründe hatte, es
keineswegs aus kleinlichen Motiven tat. Vielleicht vermag Sie dieser
Brief aufzuklären. Sie ließ ihn mir für den Fall zurück, daß wir ein
derartiges Gespräch führen sollten, wie wir es heute taten.“
Der Brief war in meiner Muttersprache geschrieben, die Netti so
gut beherrschte. Ich las folgendes:
„Mein Lenni! Ich sprach niemals mit Dir über meine früheren
persönlichen Verhältnisse, doch geschah es keineswegs deshalb, weil
ich Dir irgendetwas aus meinem Leben verheimlichen wollte. Ich
vertraue fest auf Deinen klaren Kopf und Dein edles Herz; zweifle
gar nicht daran, daß Du, wie auch immer fremd und ungewohnt
unsere Sitten für Dich sein mögen, sie zu verstehen und richtig zu
werten vermagst.
Eines jedoch fürchtete ich ... Nach der Krankheit kehrte Deine
Arbeitskraft rasch zurück, jenes seelische Gleichgewicht hingegen,
von dem in jeder Minute die Selbstbeherrschung in Wort und Tat
abhängt, hast Du noch nicht völlig wiedererlangt. Würdest Du Dich,
beeinflußt vom Augenblick und von der elementaren Gewalt, die in
der Tiefe jeder Menschenseele verborgen liegt, mir gegenüber wie
gegen eine schlechte Frau verhalten, die sich aus der
Vergewaltigung und Sklaverei der alten Welt befreit hat – Du
würdest es Dir selbst niemals verzeihen. Ja, Teuerster, ich weiß es,
Du bist gegen Dich selbst streng, bisweilen sogar grausam – diesen
Zug brachtest Du aus Eurer harten Schule mit, aus den
jahrhundertealten Kämpfen der Erdenwelt – eine einzige Sekunde
böser, schmerzlicher Entzweiung würde genügen, um in Deinem
Herzen auf unsere Liebe für immer einen dunklen Schatten zu
werfen.
Mein Lenni, ich will und kann Dich beruhigen. Möge in Deiner
Seele ewig schlummern und niemals erwachen jenes böse Gefühl,
das in die Liebe zu einem Menschen die Unruhe und Sorge um ein
lebendiges Eigentum mischt. Ich werde keine persönlichen
Verhältnisse mehr haben. Das vermag ich Dir leicht und mit
Bestimmtheit zu versprechen, weil im Vergleich zu meiner Liebe für
Dich, zu dem leidenschaftlichen Wunsch, Dir bei Deiner großen
lebendigen Aufgabe zu helfen, alles andere gering und nichtig
erscheint. Ich liebe Dich nicht nur wie eine Gattin, sondern auch wie
eine Mutter, die ihr Kind in ein neues und ihm fremdes Leben
einführt, das voller Gefahren und Mühen ist. Diese Liebe aber ist
stärker und tiefer, als irgendeine andere Liebe zwischen Mensch und
Mensch. Deshalb bedeutet auch mein Versprechen kein Opfer.
Als ich den Brief zu Ende gelesen hatte, blickte mich Nella fragend
an.
„Sie hatten Recht“, sprach ich und küßte ihr die Hand.
Auf der Suche
Der oben geschilderte Vorfall ließ in meiner Seele das Gefühl tiefster
Demütigung zurück. Noch weit schmerzlicher als früher empfand ich
die Ueberlegenheit meiner Umgebung, in der Fabrik und überall.
Zweifellos übertrieb ich diese Ueberlegenheit sowie das Gefühl der
eigenen Schwäche. Ich begann in der mich umgebenden
Dienstbereitschaft und Fürsorge eine leichte Färbung halb
verächtlicher Herablassung zu sehen, in der vorsichtigen
Zurückhaltung meiner Arbeitsgefährten eine heimliche Abneigung
gegen das niedrigere Wesen. In einer derartigen Stimmung verlor
ich die Fähigkeit genauer Beobachtung und richtiger Wertung.
In allen anderen Beziehungen blieben meine Gedanken klar,
arbeiteten nun vor allem an dem Problem, das sich auf Nettis
Abreise bezog. Ich fühlte immer stärker die Ueberzeugung, daß es
für Nettis Teilnahme an der Expedition ein mir noch unbekanntes
Motiv gab, eines, das stärker und gewichtiger war, als jene, die sie
mir gegenüber vorgebracht hatte. Der neue Beweis von Nettis Liebe
und von der ungeheueren Bedeutung, die sie meiner Mission, die
zwei Welten einander nahe zu bringen, beilegte, bestärkte mich in
der Annahme, daß sie sich ohne zwingende Gründe nicht
entschlossen haben würde, mich für lange Zeit auf dem tiefen, durch
Sandbänke und Klippen gefahrvollen Meer des fremden Lebens allein
zu lassen, mußte doch ihr heller und scharfer Verstand besser als
jeder andere begreifen, welche Gefahren mich hier bedrohten. Es
gab etwas, um das ich nicht wußte, doch war ich fest überzeugt,
dieses Etwas stehe in enger Verbindung mit mir, und es sei nötig, um
jeden Preis zu erfahren, worum es sich handle.
Ich beschloß, systematisch Nachforschungen anzustellen. Es fielen
mir Beobachtungen ein, zu denen mich einige zufällige und
unwillkürliche Andeutungen Nettis veranlaßt hatten: der beunruhigte
Ausdruck, der auf ihrem Gesicht lag und mich in Erstaunen
versetzte, sobald die Rede auf die Kolonialexpeditionen kam; ich
begann zu ahnen, daß Netti sich zu unserer Trennung nicht erst
damals entschlossen hatte, als sie mir davon sprach, sondern bereits
weit früher, schon in den ersten Tagen unserer Vereinigung.
Demnach mußte der Grund aus jener Zeit stammen. Wo aber war er
zu suchen?
Er konnte eine rein persönliche Angelegenheit Nettis sein, konnte
aber auch mit der besonderen Bedeutung der Expedition
zusammenhängen. Die erste Annahme erschien mir, nachdem ich
Nettis Brief gelesen hatte, unwahrscheinlich. Vor allem galt es also,
die Einzelheiten zu erforschen, mit jenen zu beginnen, die die
Geschichte dieser Expeditionen zu erklären vermochten.
Es verstand sich von selbst, daß die Expedition auf den Beschluß
der „Kolonialgruppe“ zurückzuführen war. – Diesen Namen trug die
Vereinigung jener Arbeiter, die aktive Teilnehmer der
interplanetarischen Reisen waren, zusammen mit dem Vorsitzenden
des Zentralen statistischen Bureaus und jener Fabriken, die die
Aetheroneffs herstellten, sowie alle für die Expedition
unentbehrlichen Mittel. Ich wußte, daß die letzte Sitzung der
„Kolonialgruppe“ während meiner Krankheit stattgefunden hatte.
Menni und Netti hatten an ihr teilgenommen. Damals befand ich
mich bereits auf dem Wege der Genesung, langweilte mich ohne
Netti und verlangte, ebenfalls der Sitzung beizuwohnen. Netti jedoch
erwiderte, dies wäre gefährlich für meine Gesundheit. Hing diese
„Gefahr“ vielleicht von etwas ab, das ich nicht wissen durfte? Ich
mußte demnach das Protokoll der Sitzung lesen, dort alles suchen,
was mit dieser Frage in Zusammenhang stehen konnte.
Doch stieß ich bereits hier auf Schwierigkeiten. In der
Kolonialbibliothek wurde mir nur die auf der Sitzung gefaßte
Resolution vorgelegt. In dieser Resolution wurde bis in alle
Einzelheiten die ganze Organisation des grandiosen Unternehmens
geschildert, doch fand ich nirgends das, was mich im Augenblick
interessierte. Ich erhielt auf meine Fragen keine Antwort. Die
Resolution wurde ohne jedes Motiv wiedergegeben, ohne
irgendeinen Hinweis auf die Ausführungen, die ihr vorangegangen
waren. Als ich dem Bibliothekar erklärte, ich wolle das Protokoll,
erwiderte er, das Protokoll werde nicht veröffentlicht, außerdem
würden detaillierte Protokolle überhaupt nicht geführt, wie dies auch
bei den technischen Sitzungen der Fall sei.
Auf den ersten Blick erschien mir dies richtig. Die Marsbewohner
veröffentlichten meist nur die „Beschlüsse“ dieser Sitzungen, sie
nahmen an, daß jede dort geäußerte verständige und nützliche
Ansicht, sowie gegenteilige Meinungen und Auffassungen besser in
Artikeln, Broschüren, Büchern usw. verfochten werden konnten, als
in einer kurzen Rede. Ueberhaupt behagte es den Marsbewohnern
nicht, die „Literatur“ übermäßig zu vermehren und man suchte bei
ihnen vergeblich etwas, das unserer „Arbeitskommission“ gleichkam;
sie bemühten sich, alles so wenig umfangreich wie möglich zu
gestalten. Im gegebenen Fall jedoch schenkte ich den Worten des
Bibliothekars keinen Glauben. Auf dieser Sitzung hatte es sich um
große und gewichtige Dinge gehandelt, als daß man sie der
öffentlichen Beurteilung hätte entziehen können, wie das bei den
gewöhnlichen technischen Fragen der Fall war.
Ich versuchte selbstverständlich mein Mißtrauen zu verbergen, um
keinerlei Verdacht zu erregen, vertiefte mich ergeben in das mir
gewährte Material und entwickelte unterdessen den Plan meines
weiteren Vorgehens.
Es war offensichtlich, daß ich von den Büchern der Bibliothek nicht
jene erhalten würde, deren ich bedurfte; entweder gab es über diese
Angelegenheit gar kein Protokoll, oder aber der Bibliothekar war auf
meine Fragen vorbereitet gewesen und versteckte es vor mir. Doch
blieb noch die Phonographen-Abteilung der Bibliothek übrig.
Dort konnten auch jene Protokolle, die nicht zur Veröffentlichung
freigegeben wurden, gefunden werden. Der Phonograph ersetzte bei
den Marsbewohnern häufig die Stenographie, und in den Archiven
wurden viele phonographische Platten der verschiedenen wichtigen
Versammlungen aufbewahrt.
Ich benützte den Augenblick, da der Bibliothekar in seine Arbeit
vertieft war und verfügte mich unbemerkt in die Phonographen-
Abteilung. Dort erbat ich von dem diensthabenden Genossen den
Katalog der Platten. Er gab ihn mir.
Aus dem Katalog ersah ich gar bald die Nummer der Platte der
mich interessierenden Sitzung und ich begab mich unter dem
Vorwand, daß ich den Genossen nicht belästigen wolle, selbst auf die
Suche. Auch hier errang ich einen Erfolg.
Es gab von dieser Sitzung fünfzehn Phonogramme. An jeder der
Platten war entsprechend dem hier üblichen Brauch ein
Inhaltsverzeichnis befestigt. Ich studierte rasch diese Verzeichnisse.
Die fünf ersten waren den Berichten über die Expedition
gewidmet, stammten noch aus einer früheren Sitzung und
beschäftigten sich mit technischen, den Aetheroneff betreffenden
Fragen.
Die Ueberschrift der vierten Platte lautete:
„Vorschlag des Zentralen statistischen Bureaus für den Uebergang
zur Massenkolonisation. Wahl der Planeten – Erde oder Venus.
Reden und Vorschläge Sternis, Nettis, Mennis und anderer. Beschluß
zu Gunsten der Venus.“
Ich fühlte, dies sei, was ich suche und steckte die Platte in den
Apparat. Was ich nun vernahm, schnitt mir für ewige Zeiten in die
Seele. Es war Folgendes.
Menni eröffnete die Sitzung als Vorsitzender des Kongresses. Als
erster ergriff der Vorsitzende des Zentralen statistischen Bureaus das
Wort.
Er bewies auf Grund genauer Zahlen, daß bei der gegebenen
Vermehrung der Bevölkerung und der Steigerung ihrer Bedürfnisse
selbst für den Fall, daß die Marsbewohner die Ausbeutung ihres
Planeten einschränkten, in etwa dreißig Jahren ein Mangel an
Lebensmitteln eintreten müsse. Dieser Gefahr vermöchte freilich die
Entdeckung der Synthese des Eiweiß aus unorganischen Stoffen zu
begegnen, doch könne niemand dafür bürgen, daß diese Entdeckung
in den nächsten dreißig Jahren gemacht würde. Deshalb sei es
unbedingt nötig, daß die Kolonialgruppe von den rein
wissenschaftlichen Expeditionen nach anderen Planeten zur
Organisation einer Massenauswanderung der Marsbewohner
übergehe. In Frage kämen zwei vom Mars aus erreichbare Planeten,
beide reich an Naturschätzen. Es müsse schleunigst beschlossen
werden, welcher der beiden als Zentrum der Kolonisation zu wählen
sei, damit dann sofort an die Ausarbeitung des Planes gegangen
werden könne.
Menni stellte die Frage, ob jemand gegen den Antrag des Redners
oder gegen dessen Motivierung etwas einzuwenden habe. Doch
verlangte niemand das Wort.
Dann warf Menni die Frage auf, welcher Planet als erster für die
Massenkolonisation gewählt werden solle.
Sterni ergriff das Wort.
Sterni
ebookgate.com