Python basic introduction¶
This is the first part of our beginner’s guide to the basics of using Python with Evennia. It’s aimed at you with limited or no programming/Python experience. But also if you are an experienced programmer new to Evennia or Python you might still pick up a thing or two. It is by necessity brief and low on detail. There are countless Python guides and tutorials, books and videos out there for learning more in-depth - use them!
- Evennia Hello world
- Importing modules
- Parsing Python errors
- Our first function
- (continued in part 2)
This quickstart assumes you have gotten Evennia started. You should
make sure that you are able to see the output from the server in the
console from which you started it. Log into the game either with a mud
localhost:4000 or by pointing a web browser to
localhost:4001/webclient. Log in as your superuser (the user you
created during install).
Below, lines starting with a single
> means command input.
Evennia Hello world¶
! which is an alias) command allows you as a
superuser to run raw Python from in-game. From the game’s input line,
enter the following:
> @py print("Hello World!")
You won’t see any return in Evennia though, instead you will just see:
>>> print("Hello world!") None
To understand what is going on: some extra info: The
function is the basic, in-built way to output text in Python. The
"..." means you are inputing a string (i.e. text). You
could also have used single-quotes
'...', Python accepts both.
The first return line (with
>>>) is just
@py echoing what you
input (we won’t include that in the examples henceforth) and the last
line just says the
@py command finished.
Where is our hello world? In Evennia,
active and that you are standing in your game directory (the one created
evennia --init during installation). Enter
to start tailing the log in the terminal (use
Ctrl-C if you need to
exit later). If you look towards the end you will find the print output
next to the log time stamp:
2017-05-07T20:20:16+0000 [stdout#info] Hello world!
As a game dev it is important to look at the console output when working in Evennia - many errors will only appear with full details here. You may sometimes have to scroll up in the history if you miss it.
To show the greeting in-game, try the following instead:
> @py me.msg("Hello world!") Hello world! None
Ignore the last
None, that’s just a return from the
itself we don’t need to care about for now. The
me is something
uniquely available in the
@py command (we could also use
it’s an alias). It represents “us”, the ones calling the
me is an example of an Object instance. Objects are
fundamental in Python and Evennia. The
me object not only represents
the character we play in the game, it also contains a lot of useful
resources for doing things with that Object. One such resource is
msg works like
You access an Object’s resources by using the full-stop character
self.msg accesses the
msg resource and then we call it like
we did print, with our “Hello World!” greeting in parentheses.
Important: something like
print(...)we refer to as a function, while
msg(...)which sits on an object is called a method.
You can try printing other things. Also try to include
|r at the
start of your string to make the output red in-game. Use
learn more color tags.
Keep your game running, then open a text editor of your choice. If your
game folder is called
mygame, create a new text file
mygame/world. This is how the file structure should
mygame/ world/ test.py
For now, only add one line to
Don’t forget to save the file. A file with the ending
referred to as a Python module. To use this in-game we have to
import it. Try this:
> @py import world.test
If you make some error (we’ll cover how to handle errors below) you may
need to run the
@reload command for your changes to take effect.
Think of the period
. as replacing
\ for Windows) in
your path. The
.py ending of
test.py is never included in this
“Python-path”, but only files with that ending can be imported this way.
mygame in that Python-path? The answer is that Evennia has
already told Python that your
mygame folder is a good place to look
for imports. So we don’t include
mygame in the path - Evennia
handles this for us.
When you import the module, the top “level” of it will execute. In this case, it will immediately print “Hello World” to the console window.
If you look in the folder you’ll also often find new files ending with
.pyc. These are compiled Python binaries that Python auto-creates when running code. Just ignore them, you should never edit those anyway.
Now try to run this a second time:
> @py import world.test
You will not see any output in the log this second time or any
subsequent times! This is not a bug. Rather it is because Python is
being clever - it stores all imported modules and to be efficient it
will avoid importing them more than once. So your
@reload first, so
Python forgets about the module and has to import it again.
We’ll get back to importing code in the second part of this tutorial. For now, let’s press on.
Parsing Python errors¶
Next, erase the single
replace it with this instead:
As you recall we used this from
@py earlier - it echoed “Hello
World!” in-game. Save your file and
@reload your server in-game -
this makes sure Evennia sees the new version of your code. Try to import
@py in the same way as earlier:
> @py import world.test
No go - this time you get an error!
File "./world/test.py", line 1, in <module> me.msg("Hello world!") NameError: name 'me' is not defined
This is called a traceback. Python’s errors are very friendly and will most of the time tell you exactly what and where things are wrong. It’s important that you learn to parse tracebacks so you can fix your code. Let’s look at this one. A traceback is to be read from the bottom up. The last line is the error Python balked at, while the two lines above it details exactly where that error was encountered.
- An error of type
NameErroris the problem …
- … more specifically it is due to the variable
menot being defined.
- This happened on the line
- … which is on line
1of the file
In our case the traceback is short. There may be many more lines above it, tracking just how different modules called each other until it got to the faulty line. That can sometimes be useful information, but reading from the bottom is always a good start.
NameError we see here is due to a module being its own isolated
thing. It knows nothing about the environment into which it is imported.
It knew what
me is not such a reserved word. As far as the
module is concerned
me is just there out of nowhere. Hence the
Our first function¶
Let’s see if we can resolve that
NameError from the previous
section. We know that
me is defined at the time we use the
command because if we do
@py me.msg("Hello World!") directly in-game
it works fine. What if we could send that
me to the
module so it knows what it is? One way to do this is with a function.
mygame/world/test.py file to look like this:
def hello_world(who): who.msg("Hello World!")
Now that we are moving onto multi-line Python code, there are some important things to remember:
- Capitalization matters in Python. It must be
whois not the same as
- Indentation matters in Python. The second line must be indented or it’s not valid code. You should also use a consistent indentation length. We strongly recommend that you set up your editor to always indent 4 spaces (not a single tab-character) when you press the TAB key - it will make your life a lot easier.
defis short for “define” and defines a function (or a method, if sitting on an object). This is a reserved Python keyword; try not to use these words anywhere else.
- A function name can not have spaces but otherwise we could have
called it almost anything. We call it
hello_world. Evennia follows Python’s standard naming style with lowercase letters and underscores. Use this style for now.
whois what we call the argument to our function. Arguments are variables we pass to the function. We could have named it anything and we could also have multiple arguments separated by commas. What
whois depends on what we pass to this function when we call it later (hint: we’ll pass
- The colon (
:) at the end of the first line indicates that the header of the function is complete.
- The indentation marks the beginning of the actual operating code of the function (the function’s body). If we wanted more lines to belong to this function those lines would all have to have to start at this indentation level.
- In the function body we take the
whoargument and treat it as we would have treated
meearlier - we expect it to have a
.msgmethod we can use to send “Hello World” to.
@reload your game to make it aware of the updated Python
module. Now we have defined our first function, let’s use it.
> @reload > @py import world.test Done (use self.msg() if you want to catch output)
Nothing happened except the normal output from
@py. That is because
the function in our module won’t do anything just by importing it. It
will only act when we call it. We will need to enter the module we
just imported and do so.
> @py import world.test ; world.test.hello_world(me) Hello world! Done (use self.msg() if you want to catch output)
There is our “Hello World”! The
; is the way to put multiple
Python-statements on one line.
Some MUD clients use
;for their own purposes to separate client-inputs. If so you’ll get a
worldis not defined. Check so you understand why this is! Change the use of
;in your client or use the Evennia web client if this is a problem.
In the second statement we access the module path we imported
world.test) and reach for the
hello_world function within. We
call the function with
me, which becomes the
who variable we
use inside the
As an exercise, try to pass something else into
hello_world. Try for example to pass who as the number
5or the simple string
"foo". You’ll get errors that they don’t have the attribute
msg. As we’ve seen,
msgavailable which is why it works (you’ll learn more about Objects like
mein the next part of this tutorial). If you are familiar with other programming languages you may be tempted to start validating
whoto make sure it works as expected. This is usually not recommended in Python which suggests it’s better to handle the error if it happens rather than to make a lot of code to prevent it from happening. See also duck typing.
This tutorial is continued in Part 2, where we’ll start learning about objects and to explore the Evennia library.