evennia/docs/latest/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.html
Evennia docbuilder action eb75a9f1ef Updated HTML docs.
2023-12-20 22:23:04 +00:00

702 lines
No EOL
63 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>3. Intro to using Python with Evennia &#8212; Evennia latest documentation</title>
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
<script src="../../../_static/jquery.js"></script>
<script src="../../../_static/underscore.js"></script>
<script src="../../../_static/doctools.js"></script>
<script src="../../../_static/language_data.js"></script>
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
<link rel="next" title="4. Overview of your new Game Dir" href="Beginner-Tutorial-Gamedir-Overview.html" />
<link rel="prev" title="2. The Tutorial World" href="Beginner-Tutorial-Tutorial-World.html" />
</head><body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Beginner-Tutorial-Gamedir-Overview.html" title="4. Overview of your new Game Dir"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="Beginner-Tutorial-Tutorial-World.html" title="2. The Tutorial World"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and How-Tos</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Overview.html" >Beginner Tutorial</a> &#187;</li>
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part1-Overview.html" accesskey="U">Part 1: What We Have</a> &#187;</li>
<li class="nav-item nav-item-this"><a href=""><span class="section-number">3. </span>Intro to using Python with Evennia</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../../../index.html">
<img class="logo" src="../../../_static/evennia_logo.png" alt="Logo"/>
</a></p>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" />
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
<h3><a href="../../../index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">3. Intro to using Python with Evennia</a><ul>
<li><a class="reference internal" href="#evennia-hello-world">3.1. Evennia Hello world</a></li>
<li><a class="reference internal" href="#making-some-text-graphics">3.2. Making some text graphics</a><ul>
<li><a class="reference internal" href="#format">3.2.1. .format()</a></li>
<li><a class="reference internal" href="#f-strings">3.2.2. f-strings</a></li>
<li><a class="reference internal" href="#colored-text">3.2.3. Colored text</a></li>
</ul>
</li>
<li><a class="reference internal" href="#importing-code-from-other-modules">3.3. Importing code from other modules</a><ul>
<li><a class="reference internal" href="#our-first-own-function">3.3.1. Our first own function</a></li>
</ul>
</li>
<li><a class="reference internal" href="#sending-text-to-others">3.4. Sending text to others</a></li>
<li><a class="reference internal" href="#parsing-python-errors">3.5. Parsing Python errors</a></li>
<li><a class="reference internal" href="#passing-arguments-to-functions">3.6. Passing arguments to functions</a></li>
<li><a class="reference internal" href="#finding-others-to-send-to">3.7. Finding others to send to</a></li>
<li><a class="reference internal" href="#multi-line-py">3.8. Multi-line py</a></li>
<li><a class="reference internal" href="#other-ways-to-test-python-code">3.9. Other ways to test Python code</a></li>
<li><a class="reference internal" href="#ipython">3.10. ipython</a></li>
<li><a class="reference internal" href="#conclusions">3.11. Conclusions</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="Beginner-Tutorial-Tutorial-World.html"
title="previous chapter"><span class="section-number">2. </span>The Tutorial World</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="Beginner-Tutorial-Gamedir-Overview.html"
title="next chapter"><span class="section-number">4. </span>Overview of your new Game Dir</a></p>
<div role="note" aria-label="source link">
<!--h3>This Page</h3-->
<ul class="this-page-menu">
<li><a href="../../../_sources/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Python-basic-introduction.md.txt"
rel="nofollow">Show Page Source</a></li>
</ul>
</div><h3>Links</h3>
<ul>
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
<li><a href="http://games.evennia.com">Game Index</a> </li>
<li>
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
<a href="https://evennia.blogspot.com/">Blog</a>
</li>
</ul>
<h3>Doc Versions</h3>
<ul>
<li><a href="Beginner-Tutorial-Python-basic-introduction.html">latest (main branch)</a></li>
<li><a href="../../3.x/index.html">3.x (v3.0.0 branch)</a></li>
<li><a href="../../2.x/index.html">2.x (v2.0.0 branch)</a></li>
<li><a href="../../1.x/index.html">1.x (v1.0.0 branch)</a></li>
<li><a href="../../0.x/index.html">0.x (v0.9.5 branch)</a></li>
</ul>
</div>
</div>
<div class="bodywrapper">
<div class="body" role="main">
<section class="tex2jax_ignore mathjax_ignore" id="intro-to-using-python-with-evennia">
<h1><span class="section-number">3. </span>Intro to using Python with Evennia<a class="headerlink" href="#intro-to-using-python-with-evennia" title="Permalink to this headline"></a></h1>
<p>Time to dip our toe into some coding! Evennia is written and extended in <a class="reference external" href="https://python.org">Python</a>. Python is a mature and professional programming language that is very fast to work with.</p>
<p>That said, even though Python is widely considered easy to learn, we can only cover the basics in these lessons. While we will hopefully get you started with the most important bits you need, you may likely need to compliment with some learning on your own. Luckily theres a vast amount of free online learning resources available for Python. See our <a class="reference internal" href="../../../Links.html"><span class="doc std std-doc">link section</span></a> for some examples.</p>
<blockquote>
<div><p>While this will be quite basic if you are an experienced developer, you may want to at least stay around for the first few sections where we cover how to run Python from inside Evennia.</p>
</div></blockquote>
<p>First, if you were quelling yourself to play the tutorial world, make sure to get your
superuser powers back:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> unquell
</pre></div>
</div>
<section id="evennia-hello-world">
<h2><span class="section-number">3.1. </span>Evennia Hello world<a class="headerlink" href="#evennia-hello-world" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">py</span></code> Command (or <code class="docutils literal notranslate"><span class="pre">!</span></code>, which is an alias) allows you as a superuser to execute raw Python from in-game. This is useful for quick testing. From the games input line, enter the following:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;Hello World!&quot;)
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Command input</p>
<p>The line with <code class="docutils literal notranslate"><span class="pre">&gt;</span></code> indicates input to enter in-game, while the lines below are the
expected return from that input.</p>
</aside>
<p>You will see</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; print(&quot;Hello world!&quot;)
Hello World!
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">print(...)</span></code> <em>function</em> is the basic, in-built way to output text in Python. We are sending “Hello World” as a single <em>argument</em> to this function. If we were to send multiple arguments, theyd be separated by commas.</p>
<p>The quotes <code class="docutils literal notranslate"><span class="pre">&quot;...&quot;</span></code> mean that you are inputting a <em>string</em> (i.e. text). You could also have used single-quotes <code class="docutils literal notranslate"><span class="pre">'...'</span></code> - Python accepts both.</p>
<blockquote>
<div><p>A third way to enter Python strings is to use triple-quotes (<code class="docutils literal notranslate"><span class="pre">&quot;&quot;&quot;...&quot;&quot;&quot;</span></code> or <code class="docutils literal notranslate"><span class="pre">'''...'''</span></code>. This is used for longer strings stretching across multiple lines. When we insert code directly to <code class="docutils literal notranslate"><span class="pre">py</span></code> like this we can only use one line though.</p>
</div></blockquote>
</section>
<section id="making-some-text-graphics">
<h2><span class="section-number">3.2. </span>Making some text graphics<a class="headerlink" href="#making-some-text-graphics" title="Permalink to this headline"></a></h2>
<p>When making a text-game you will, unsurprisingly, be working a lot with text. Even if you have the occational button or even graphical element, the normal process is for the user to input commands as text and get text back. As we saw above, a piece of text is called a <em>string</em> in Python and is enclosed in either single- or double-quotes.</p>
<p>Strings can be added together:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a &quot; + &quot;breaking change.&quot;)
This is a breaking change.
</pre></div>
</div>
<p>A string multiplied with a number will repeat that string as many times:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;|&quot; + &quot;-&quot; * 40 + &quot;|&quot;)
|----------------------------------------|
</pre></div>
</div>
<p>or</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;A&quot; + &quot;a&quot; * 5 + &quot;rgh!&quot;)
Aaaaaargh!
</pre></div>
</div>
<section id="format">
<h3><span class="section-number">3.2.1. </span>.format()<a class="headerlink" href="#format" title="Permalink to this headline"></a></h3>
<aside class="sidebar">
<p class="sidebar-title">Functions and Methods</p>
<ul class="simple">
<li><p>Function: Something that performs an action when you call it with zero or more <code class="docutils literal notranslate"><span class="pre">arguments</span></code>. A function is stand-alone in a python module, like <code class="docutils literal notranslate"><span class="pre">print()</span></code></p></li>
<li><p>Method: A function that sits “on” an object. It is accessed via the <code class="docutils literal notranslate"><span class="pre">.</span></code> operator, like <code class="docutils literal notranslate"><span class="pre">obj.msg()</span></code> or, in this case, <code class="docutils literal notranslate"><span class="pre">&lt;string&gt;.format()</span></code>.</p></li>
</ul>
</aside>
<p>While combining different strings is useful, even more powerful is the ability to modify the contents of the string in-place. There are several ways to do this in Python and well show two of them here. The first is to use the <code class="docutils literal notranslate"><span class="pre">.format</span></code> <em>method</em> of the string:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a {} idea!&quot;.format(&quot;good&quot;))
This is a good idea!
</pre></div>
</div>
<p>A method can be thought of as a resource “on” another object. The method knows on which object it sits and can thus affect it in various ways. You access it with the period <code class="docutils literal notranslate"><span class="pre">.</span></code>. In this case, the string has a resource <code class="docutils literal notranslate"><span class="pre">format(...)</span></code> that modifies it. More specifically, it replaced the <code class="docutils literal notranslate"><span class="pre">{}</span></code> marker inside the string with the value passed to the format. You can do so many times:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is a {} idea!&quot;.format(&quot;good&quot;))
This is a good idea!
</pre></div>
</div>
<p>or</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;This is the {} and {} {} idea!&quot;.format(&quot;first&quot;, &quot;second&quot;, &quot;great&quot;))
This is the first and second great idea!
</pre></div>
</div>
<blockquote>
<div><p>Note the double-parenthesis at the end - the first closes the <code class="docutils literal notranslate"><span class="pre">format(...</span></code> method and the outermost closes the <code class="docutils literal notranslate"><span class="pre">print(...</span></code>. Not closing them will give you a scary <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code>. We will talk a little more about errors in the next section, for now just fix until it prints as expected.</p>
</div></blockquote>
<p>Here we passed three comma-separated strings as <em>arguments</em> to the strings <code class="docutils literal notranslate"><span class="pre">format</span></code> method. These replaced the <code class="docutils literal notranslate"><span class="pre">{}</span></code> markers in the same order as they were given.</p>
<p>The input does not have to be strings either:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;STR: {}, DEX: {}, INT: {}&quot;.format(12, 14, 8))
STR: 12, DEX: 14, INT: 8
</pre></div>
</div>
<p>To separate two Python instructions on the same line, you use the semi-colon, <code class="docutils literal notranslate"><span class="pre">;</span></code>. Try this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py a = &quot;awesome sauce&quot; ; print(&quot;This is {}!&quot;.format(a))
This is awesome sauce!
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>MUD clients and semi-colon</p>
<p>Some MUD clients use the semi-colon <code class="docutils literal notranslate"><span class="pre">;</span></code> to split client-inputs
into separate sends. If so, the above will give an error. Most clients allow you to run in verbatim mode or to remap to use some other separator than <code class="docutils literal notranslate"><span class="pre">;</span></code>. If you still have trouble, use the Evennia web client.</p>
</div>
<p>What happened here was that we <em>assigned</em> the string <code class="docutils literal notranslate"><span class="pre">&quot;awesome</span> <span class="pre">sauce&quot;</span></code> to a <em>variable</em> we chose to name <code class="docutils literal notranslate"><span class="pre">a</span></code>. In the next statement, Python remembered what <code class="docutils literal notranslate"><span class="pre">a</span></code> was and we passed that into <code class="docutils literal notranslate"><span class="pre">format()</span></code> to get the output. If you replaced the value of <code class="docutils literal notranslate"><span class="pre">a</span></code> with something else in between, <em>that</em> would be printed instead.</p>
<p>Heres the stat-example again, moving the stats to variables (here we just set them, but in a real game they may be changed over time, or modified by circumstance):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py stren, dext, intel = 13, 14, 8 ; print(&quot;STR: {}, DEX: {}, INT: {}&quot;.format(stren, dext, intel))
STR: 13, DEX: 14, INT: 8
</pre></div>
</div>
<p>The point is that even if the values of the stats change, the print() statement would not change - it just keeps pretty-printing whatever is given to it.</p>
<p>You can also use named markers, like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; py print(&quot;STR: {stren}, INT: {intel}, STR again: {stren}&quot;.format(dext=10, intel=18, stren=9))
STR: 9, INT: 18, Str again: 9
</pre></div>
</div>
<p>the <code class="docutils literal notranslate"><span class="pre">key=value</span></code> pairs we add are called <em>keyword arguments</em> for the <code class="docutils literal notranslate"><span class="pre">format()</span></code> method. Each named argument will go to the matching <code class="docutils literal notranslate"><span class="pre">{key}</span></code> in the string. When using keywords, the order we add them doesnt matter. We have no <code class="docutils literal notranslate"><span class="pre">{dext}</span></code> and two <code class="docutils literal notranslate"><span class="pre">{stren}</span></code> in the string, and that works fine.</p>
</section>
<section id="f-strings">
<h3><span class="section-number">3.2.2. </span>f-strings<a class="headerlink" href="#f-strings" title="Permalink to this headline"></a></h3>
<p>Using <code class="docutils literal notranslate"><span class="pre">.format()</span></code> is powerful (and there is a <a class="reference external" href="https://www.w3schools.com/python/ref_string_format.asp">lot more</a> you can do with it). But the <em>f-string</em> can be even more convenient. An f-string looks like a normal string … except there is an <code class="docutils literal notranslate"><span class="pre">f</span></code> front of it, like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>f&quot;this is now an f-string.&quot;
</pre></div>
</div>
<p>An f-string on its own is just like any other string. But lets redo the example we did before, using an f-string:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py a = &quot;awesome sauce&quot; ; print(f&quot;This is {a}!&quot;)
This is awesome sauce!
</pre></div>
</div>
<p>We insert that <code class="docutils literal notranslate"><span class="pre">a</span></code> variable directly into the f-string using <code class="docutils literal notranslate"><span class="pre">{a}</span></code>. Fewer parentheses to
remember and arguable easier to read as well!</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py stren, dext, intel = 13, 14, 8 ; print(f&quot;STR: {stren}, DEX: {dext}, INT: {intel}&quot;)
STR: 13, DEX: 14, INT: 8
</pre></div>
</div>
<p>In modern Python code, f-strings are more often used than <code class="docutils literal notranslate"><span class="pre">.format()</span></code> but to read code you need to be aware of both.</p>
<p>We will be exploring more complex string concepts when we get to creating Commands and need to parse and understand player input.</p>
</section>
<section id="colored-text">
<h3><span class="section-number">3.2.3. </span>Colored text<a class="headerlink" href="#colored-text" title="Permalink to this headline"></a></h3>
<p>Python itself knows nothing about colored text, this is an Evennia thing. Evennia supports the standard color schemes of traditional MUDs.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;|rThis is red text!|n This is normal color.&quot;)
</pre></div>
</div>
<p>Adding that <code class="docutils literal notranslate"><span class="pre">|r</span></code> at the start will turn our output bright red. <code class="docutils literal notranslate"><span class="pre">|R</span></code> will make it dark red. <code class="docutils literal notranslate"><span class="pre">|n</span></code>
gives the normal text color. You can also use RGB (Red-Green-Blue) values from 0-5 (Xterm256 colors):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py print(&quot;|043This is a blue-green color.|[530|003 Now dark blue text on orange background.&quot;)
</pre></div>
</div>
<blockquote>
<div><p>If you dont see the expected color, your client or terminal may not support Xterm256 (or
color at all). Use the Evennia webclient.</p>
</div></blockquote>
<p>Use the commands <code class="docutils literal notranslate"><span class="pre">color</span> <span class="pre">ansi</span></code> or <code class="docutils literal notranslate"><span class="pre">color</span> <span class="pre">xterm</span></code> to see which colors are available. Experiment! You can also read a lot more in the <a class="reference internal" href="../../../Concepts/Colors.html"><span class="doc std std-doc">Colors</span></a> documentation.</p>
</section>
</section>
<section id="importing-code-from-other-modules">
<h2><span class="section-number">3.3. </span>Importing code from other modules<a class="headerlink" href="#importing-code-from-other-modules" title="Permalink to this headline"></a></h2>
<p>As we saw in the previous sections, we used <code class="docutils literal notranslate"><span class="pre">.format</span></code> to format strings and <code class="docutils literal notranslate"><span class="pre">me.msg</span></code> to access the <code class="docutils literal notranslate"><span class="pre">msg</span></code> method on <code class="docutils literal notranslate"><span class="pre">me</span></code>. This use of the full-stop character is used to access all sorts of resources, including that in other Python modules.</p>
<p>Keep your game running, then open a text editor of your choice. If your game folder is called
<code class="docutils literal notranslate"><span class="pre">mygame</span></code>, create a new text file <code class="docutils literal notranslate"><span class="pre">test.py</span></code> in the subfolder <code class="docutils literal notranslate"><span class="pre">mygame/world</span></code>. This is how the file
structure should look:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">mygame</span><span class="o">/</span>
<span class="n">world</span><span class="o">/</span>
<span class="n">test</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>For now, only add one line to <code class="docutils literal notranslate"><span class="pre">test.py</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Python module</p>
<p>This is a text file with the <code class="docutils literal notranslate"><span class="pre">.py</span></code> file ending. A module
contains Python source code and from within Python one can
access its contents by importing it via its python-path.</p>
</aside>
<p>Dont forget to <em>save</em> the file. We just created our first Python <em>module</em>!
To use this in-game we have to <em>import</em> it. Try this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
Hello World
</pre></div>
</div>
<p>If you make some error (well cover how to handle errors below), make sure the text looks exactly like above and then run the <code class="docutils literal notranslate"><span class="pre">reload</span></code> command in-game for your changes to take effect.</p>
<p>… So as you can see, importing <code class="docutils literal notranslate"><span class="pre">world.test</span></code> actually means importing <code class="docutils literal notranslate"><span class="pre">world/test.py</span></code>. Think of the period <code class="docutils literal notranslate"><span class="pre">.</span></code> as replacing <code class="docutils literal notranslate"><span class="pre">/</span></code> (or <code class="docutils literal notranslate"><span class="pre">\</span></code> for Windows) in your path.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">.py</span></code> ending of <code class="docutils literal notranslate"><span class="pre">test.py</span></code> is never included in this “Python-path”, but <em>only</em> files with that ending can be imported this way. Where is <code class="docutils literal notranslate"><span class="pre">mygame</span></code> in that Python-path? The answer is that Evennia has already told Python that your <code class="docutils literal notranslate"><span class="pre">mygame</span></code> folder is a good place to look for imports. So we should not include <code class="docutils literal notranslate"><span class="pre">mygame</span></code> in the path - Evennia handles this for us.</p>
<p>When you import the module, the top “level” of it will execute. In this case, it will immediately
print “Hello World”.</p>
<p>Now try to run this a second time:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
</pre></div>
</div>
<p>You will <em>not</em> see any output this or any subsequent times! This is not a bug. Rather it is because of how Python importing works - it stores all imported modules and will avoid importing them more than once. So your <code class="docutils literal notranslate"><span class="pre">print</span></code> will only run the first time, when the module is first imported.</p>
<p>Try this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
</pre></div>
</div>
<p>And then</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test
Hello World!
</pre></div>
</div>
<p>Now we see it again. The <code class="docutils literal notranslate"><span class="pre">reload</span></code> wiped the servers memory of what was imported, so it had to import it anew. Youd have to do this every time you wanted the hello-world to show, which is not very useful.</p>
<blockquote>
<div><p>Well get back to more advanced ways to import code in <a class="reference internal" href="Beginner-Tutorial-Python-classes-and-objects.html#importing-things"><span class="std std-doc">a later lesson</span></a> - this is an important topic. But for now, lets press on and resolve this particular problem.</p>
</div></blockquote>
<section id="our-first-own-function">
<h3><span class="section-number">3.3.1. </span>Our first own function<a class="headerlink" href="#our-first-own-function" title="Permalink to this headline"></a></h3>
<p>We want to be able to print our hello-world message at any time, not just once after a server
reload. Change your <code class="docutils literal notranslate"><span class="pre">mygame/world/test.py</span></code> file to look like this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<aside class="sidebar">
<p>If you are coming from some other language like Javascript or C you may be familiar with variables and functions mixing cases in names, like <code class="docutils literal notranslate"><span class="pre">helloWorld()</span></code>. While you <em>could</em> choose to name things this way, it will clash with other Python code - Python standard is to use lower-case and underscores <code class="docutils literal notranslate"><span class="pre">_</span></code> for all variables and methods.</p>
</aside>
<p>As we are moving to multi-line Python code, there are some important things to remember:</p>
<ul class="simple">
<li><p>Capitalization matters in Python. It must be <code class="docutils literal notranslate"><span class="pre">def</span></code> and not <code class="docutils literal notranslate"><span class="pre">DEF</span></code>, <code class="docutils literal notranslate"><span class="pre">hello_world()</span></code> is not the same as <code class="docutils literal notranslate"><span class="pre">Hello_World()</span></code>.</p></li>
<li><p>Indentation matters in Python. The second line must be indented or its not valid code. You should also use a consistent indentation length. We <em>strongly</em> recommend that you, for your own sanitys sake, set up your editor to always indent <em>4 spaces</em> (<strong>not</strong> a single tab-character) when you press the TAB key.</p></li>
</ul>
<p>So about that function. Line 1:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">def</span></code> is short for “define” and defines a <em>function</em> (or a <em>method</em>, if sitting on an object). This is a <a class="reference external" href="https://docs.python.org/2.5/ref/keywords.html">reserved Python keyword</a>; try not to use these words anywhere else.</p></li>
<li><p>A function name can not have spaces but otherwise we could have called it almost anything. We call it <code class="docutils literal notranslate"><span class="pre">hello_world</span></code>. Evennia follows <a class="reference internal" href="../../../Coding/Evennia-Code-Style.html"><span class="doc std std-doc">Pythons standard naming style</span></a> with lowercase letters and underscores. We recommend you do the same.</p></li>
<li><p>The colon (<code class="docutils literal notranslate"><span class="pre">:</span></code>) at the end of line 1 indicates that the header of the function is complete.</p></li>
</ul>
<p>Line 2:</p>
<ul class="simple">
<li><p>The indentation marks the beginning of the actual operating code of the function (the functions <em>body</em>). If we wanted more lines to belong to this function those lines would all have to start at least at this indentation level.</p></li>
</ul>
<p>Now lets try this out. First <code class="docutils literal notranslate"><span class="pre">reload</span></code> your game to have it pick up our updated Python module, then import it.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; reload
&gt; py import world.test
</pre></div>
</div>
<p>Nothing happened! That is because the function in our module wont do anything just by importing it (this is what we wanted). It will only act when we <em>call</em> it. So we need to first import the module and then access the function within:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world()
Hello world!
</pre></div>
</div>
<p>There is our “Hello World”! As mentioned earlier, use use semi-colon to put multiple Python-statements on one line. Note also the previous warning about mud-clients using the <code class="docutils literal notranslate"><span class="pre">;</span></code> to their own ends.</p>
<p>So what happened there? First we imported <code class="docutils literal notranslate"><span class="pre">world.test</span></code> as usual. But this time the top level of the module only defined a function. It didnt actually execute the body of that function.</p>
<p>By adding <code class="docutils literal notranslate"><span class="pre">()</span></code> to the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function we <em>call</em> it. That is, we execute the body of the function and print our text. We can now redo this as many times as we want without having to <code class="docutils literal notranslate"><span class="pre">reload</span></code> in between:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world()
Hello world!
&gt; py import world.test ; world.test.hello_world()
Hello world!
</pre></div>
</div>
</section>
</section>
<section id="sending-text-to-others">
<h2><span class="section-number">3.4. </span>Sending text to others<a class="headerlink" href="#sending-text-to-others" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">print</span></code> command is a standard Python structure. We can use that here in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command since we can se the output. Its great for debugging and quick testing. But if you need to send a text to an actual player, <code class="docutils literal notranslate"><span class="pre">print</span></code> wont do, because it doesnt know <em>who</em> to send to. Try this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py me.msg(&quot;Hello world!&quot;)
Hello world!
</pre></div>
</div>
<p>This looks the same as the <code class="docutils literal notranslate"><span class="pre">print</span></code> result, but we are now actually messaging a specific <em>object</em>, <code class="docutils literal notranslate"><span class="pre">me</span></code>. The <code class="docutils literal notranslate"><span class="pre">me</span></code> is a shortcut to us, the one running the <code class="docutils literal notranslate"><span class="pre">py</span></code> command. It is not some special Python thing, but something Evennia just makes available in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command for convenience (<code class="docutils literal notranslate"><span class="pre">self</span></code> is an alias).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">me</span></code> is an example of an <em>Object instance</em>. Objects are fundamental in Python and Evennia. The <code class="docutils literal notranslate"><span class="pre">me</span></code> object also contains a lot of useful resources for doing things with that object. We access those resources with <code class="docutils literal notranslate"><span class="pre">.</span></code>.</p>
<p>One such resource is <code class="docutils literal notranslate"><span class="pre">msg</span></code>, which works like <code class="docutils literal notranslate"><span class="pre">print</span></code> except it sends the text to the object it
is attached to. So if we, for example, had an object <code class="docutils literal notranslate"><span class="pre">you</span></code>, doing <code class="docutils literal notranslate"><span class="pre">you.msg(...)</span></code> would send a message to the object <code class="docutils literal notranslate"><span class="pre">you</span></code>.</p>
<p>For now, <code class="docutils literal notranslate"><span class="pre">print</span></code> and <code class="docutils literal notranslate"><span class="pre">me.msg</span></code> behaves the same, just remember that <code class="docutils literal notranslate"><span class="pre">print</span></code> is mainly used for
debugging and <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> will be more useful for you in the future.</p>
</section>
<section id="parsing-python-errors">
<h2><span class="section-number">3.5. </span>Parsing Python errors<a class="headerlink" href="#parsing-python-errors" title="Permalink to this headline"></a></h2>
<p>Lets try this new text-sending in the function we just created. Go back to
your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> file and Replace the function with this instead:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
<span class="n">me</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Save your file and <code class="docutils literal notranslate"><span class="pre">reload</span></code> your server to tell Evennia to re-import new code,
then run it like before:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span> &gt; py import world.test ; world.test.hello_world()
</pre></div>
</div>
<p>No go - this time you get an <em>error</em>!</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">File</span> <span class="s2">&quot;./world/test.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">2</span><span class="p">,</span> <span class="ow">in</span> <span class="n">hello_world</span>
<span class="n">me</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
<span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s1">&#39;me&#39;</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span>
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Errors in the logs</p>
<p>In regular use, tracebacks will often appear in the log rather than
in the game. Use <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">--log</span></code> to view the log in the terminal. Make
sure to scroll back if you expect an error and dont see it. Use
<code class="docutils literal notranslate"><span class="pre">Ctrl-C</span></code> (or <code class="docutils literal notranslate"><span class="pre">Cmd-C</span></code> on Mac) to exit the log-view.</p>
</aside>
<p>This is called a <em>traceback</em>. Pythons errors are very friendly and will most of the time tell you exactly what and where things go wrong. Its important that you learn to parse tracebacks so you know how to fix your code.</p>
<p>A traceback is to be read from the <em>bottom up</em>:</p>
<ul class="simple">
<li><p>(line 3) An error of type <code class="docutils literal notranslate"><span class="pre">NameError</span></code> is the problem …</p></li>
<li><p>(line 3) … more specifically it is due to the variable <code class="docutils literal notranslate"><span class="pre">me</span></code> not being defined.</p></li>
<li><p>(line 2) This happened on the line <code class="docutils literal notranslate"><span class="pre">me.msg(&quot;Hello</span> <span class="pre">world!&quot;)</span></code></p></li>
<li><p>(line 1) … which is on line <code class="docutils literal notranslate"><span class="pre">2</span></code> of the file <code class="docutils literal notranslate"><span class="pre">./world/test.py</span></code>.</p></li>
</ul>
<p>In our case the traceback is short. There may be many more lines above it, tracking just how
different modules called each other until the program got to the faulty line. That can
sometimes be useful information, but reading from the bottom is always a good start.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">NameError</span></code> 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 <code class="docutils literal notranslate"><span class="pre">print</span></code> is because that is a special <a class="reference external" href="https://docs.python.org/2.5/ref/keywords.html">reserved Python keyword</a>. But <code class="docutils literal notranslate"><span class="pre">me</span></code> is <em>not</em> such a reserved word (as mentioned, its just something Evennia came up with for convenience in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command). As far as the module is concerned <code class="docutils literal notranslate"><span class="pre">me</span></code> is an unfamiliar name, appearing out of nowhere. Hence the <code class="docutils literal notranslate"><span class="pre">NameError</span></code>.</p>
</section>
<section id="passing-arguments-to-functions">
<h2><span class="section-number">3.6. </span>Passing arguments to functions<a class="headerlink" href="#passing-arguments-to-functions" title="Permalink to this headline"></a></h2>
<p>We know that <code class="docutils literal notranslate"><span class="pre">me</span></code> exists at the point when we run the <code class="docutils literal notranslate"><span class="pre">py</span></code> command, because we can do <code class="docutils literal notranslate"><span class="pre">py</span> <span class="pre">me.msg(&quot;Hello</span> <span class="pre">World!&quot;)</span></code> with no problem. So lets <em>pass</em> that me along to the function so it knows what it should be. Go back to your <code class="docutils literal notranslate"><span class="pre">test.py</span></code> and change it to this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello_world</span><span class="p">(</span><span class="n">who</span><span class="p">):</span>
<span class="n">who</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;Hello World!&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>We now added an <em>argument</em> to the function. We could have named it anything. Whatever <code class="docutils literal notranslate"><span class="pre">who</span></code> is, we will call a method <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> on it.</p>
<p>As usual, <code class="docutils literal notranslate"><span class="pre">reload</span></code> the server to make sure the new code is available.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py import world.test ; world.test.hello_world(me)
Hello World!
</pre></div>
</div>
<p>Now it worked. We <em>passed</em> <code class="docutils literal notranslate"><span class="pre">me</span></code> to our function. It will appear inside the function renamed as <code class="docutils literal notranslate"><span class="pre">who</span></code> and now the function works and prints as expected. Note how the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function doesnt care <em>what</em> you pass into it as long as it has a <code class="docutils literal notranslate"><span class="pre">.msg()</span></code> method on it. So you could reuse this function over and over for other suitable targets.</p>
<blockquote>
<div><p><strong>Extra Credit:</strong> As an exercise, try to pass something else into <code class="docutils literal notranslate"><span class="pre">hello_world</span></code>. Try for example
to pass the number <code class="docutils literal notranslate"><span class="pre">5</span></code> or the string <code class="docutils literal notranslate"><span class="pre">&quot;foo&quot;</span></code>. Youll get errors telling you that they dont have
the attribute <code class="docutils literal notranslate"><span class="pre">msg</span></code>. They dont care about <code class="docutils literal notranslate"><span class="pre">me</span></code> itself not being a string or a number. If you are
familiar with other programming languages (especially C/Java) you may be tempted to start <em>validating</em> <code class="docutils literal notranslate"><span class="pre">who</span></code> to make sure its of the right type before you send it. This is usually not recommended in Python. Python philosophy is to <a class="reference external" href="https://docs.python.org/2/tutorial/errors.html">handle</a> the error if it happens
rather than to add a lot of code to prevent it from happening. See <a class="reference external" href="https://en.wikipedia.org/wiki/Duck_typing">duck typing</a>
and the concept of <em>Leap before you Look</em>.</p>
</div></blockquote>
</section>
<section id="finding-others-to-send-to">
<h2><span class="section-number">3.7. </span>Finding others to send to<a class="headerlink" href="#finding-others-to-send-to" title="Permalink to this headline"></a></h2>
<p>Lets wrap up this first Python <code class="docutils literal notranslate"><span class="pre">py</span></code> crash-course by finding someone else to send to.</p>
<p>In Evennias <code class="docutils literal notranslate"><span class="pre">contrib/</span></code> folder (<code class="docutils literal notranslate"><span class="pre">evennia/contrib/tutorial_examples/mirror.py</span></code>) is a handy little object called the <code class="docutils literal notranslate"><span class="pre">TutorialMirror</span></code>. The mirror will echo whatever is being sent to it to
the room it is in.</p>
<p>On the game command-line, lets create a mirror:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; create/drop mirror:contrib.tutorials.mirror.TutorialMirror
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">Creating objects</p>
<p>The <code class="docutils literal notranslate"><span class="pre">create</span></code> command was first used to create boxes in the
<a class="reference internal" href="Beginner-Tutorial-Building-Quickstart.html"><span class="doc std std-doc">Building Stuff</span></a> tutorial. You should now recognize
that it uses a “python-path” to tell Evennia where to load the mirrors code from.</p>
</aside>
<p>A mirror should appear in your location.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; look mirror
mirror shows your reflection:
This is User #1
</pre></div>
</div>
<p>What you are seeing is actually your own avatar in the game, the same thing that is available as <code class="docutils literal notranslate"><span class="pre">me</span></code> in the <code class="docutils literal notranslate"><span class="pre">py</span></code> command.</p>
<p>What we are aiming for now is the equivalent of <code class="docutils literal notranslate"><span class="pre">mirror.msg(&quot;Mirror</span> <span class="pre">Mirror</span> <span class="pre">on</span> <span class="pre">the</span> <span class="pre">wall&quot;)</span></code>. But the first thing that comes to mind will not work:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py mirror.msg(&quot;Mirror, Mirror on the wall ...&quot;)
NameError: name &#39;mirror&#39; is not defined.
</pre></div>
</div>
<p>This is not surprising: Python knows nothing about “mirrors” or locations or anything. The <code class="docutils literal notranslate"><span class="pre">me</span></code> weve been using is, as mentioned, just a convenient thing the Evennia devs makes available to the <code class="docutils literal notranslate"><span class="pre">py</span></code> command. They couldnt possibly predict that you wanted to talk to mirrors.</p>
<p>Instead we will need to <em>search</em> for that <code class="docutils literal notranslate"><span class="pre">mirror</span></code> object before we can send to it. Make sure you are in the same location as the mirror and try:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py me.search(&quot;mirror&quot;)
mirror
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">me.search(&quot;name&quot;)</span></code> will, by default, search and <em>return</em> an object with the given name found in <em>the same location</em> as the <code class="docutils literal notranslate"><span class="pre">me</span></code> object is. If it cant find anything youll see an error.</p>
<aside class="sidebar">
<p class="sidebar-title">Function returns</p>
<p>Whereas a function like <code class="docutils literal notranslate"><span class="pre">print</span></code> only prints its arguments, its very common
for functions/methods to <code class="docutils literal notranslate"><span class="pre">return</span></code> a result of some kind. Think of the function
as a machine - you put something in and out comes a result you can use. In the case of <code class="docutils literal notranslate"><span class="pre">me.search</span></code>, it will perform a database search and spit out the object it finds.</p>
</aside>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py me.search(&quot;dummy&quot;)
Could not find &#39;dummy&#39;.
</pre></div>
</div>
<p>Wanting to find things in the same location is very common, but as we continue well
find that Evennia provides ample tools for tagging, searching and finding things from all over your game.</p>
<p>Now that we know how to find the mirror object, we just need to use that instead of <code class="docutils literal notranslate"><span class="pre">me</span></code>!</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py mirror = self.search(&quot;mirror&quot;) ; mirror.msg(&quot;Mirror, Mirror on the wall ...&quot;)
mirror echoes back to you:
&quot;Mirror, Mirror on the wall ...&quot;
</pre></div>
</div>
<p>The mirror is useful for testing because its <code class="docutils literal notranslate"><span class="pre">.msg</span></code> method just echoes whatever is sent to it back to the room. More common would be to talk to a player character, in which case the text you sent would have appeared in their game client.</p>
</section>
<section id="multi-line-py">
<h2><span class="section-number">3.8. </span>Multi-line py<a class="headerlink" href="#multi-line-py" title="Permalink to this headline"></a></h2>
<p>So far we have use <code class="docutils literal notranslate"><span class="pre">py</span></code> in single-line mode, using <code class="docutils literal notranslate"><span class="pre">;</span></code> to separate multiple inputs. This is very convenient when you want to do some quick testing. But you can also start a full multi-line Python interactive interpreter inside Evennia.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; py
Evennia Interactive Python mode
Python 3.11.0 (default, Nov 22 2022, 11:21:55)
[GCC 8.2.0] on Linux
[py mode - quit() to exit]
</pre></div>
</div>
<p>(the details of the output will vary with your Python version and OS). You are now in python interpreter mode. It means
that <em>everything</em> you insert from now on will become a line of Python (you can no longer look around or do other
commands).</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; print(&quot;Hello World&quot;)
&gt;&gt;&gt; print(&quot;Hello World&quot;)
Hello World
[py mode - quit() to exit]
</pre></div>
</div>
<p>Note that we didnt need to put <code class="docutils literal notranslate"><span class="pre">py</span></code> in front now. The system will also echo your input (thats the bit after the <code class="docutils literal notranslate"><span class="pre">&gt;&gt;&gt;</span></code>). For brevity in this tutorual well turn the echo off. First exit <code class="docutils literal notranslate"><span class="pre">py</span></code> and then start again with the <code class="docutils literal notranslate"><span class="pre">/noecho</span></code> flag.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Closing the Python console.
&gt; py/noecho
Evennia Interactive Python mode (no echoing of prompts)
Python 3.11.0 (default, Nov 22 2022, 11:21:56)
[GCC 8.2.0] on Linux
[py mode - quit() to exit]
</pre></div>
</div>
<aside class="sidebar">
<p class="sidebar-title">interactive py</p>
<ul class="simple">
<li><p>Start with <code class="docutils literal notranslate"><span class="pre">py</span></code>.</p></li>
<li><p>Use <code class="docutils literal notranslate"><span class="pre">py/noecho</span></code> if you dont want your input to be echoed for every line.</p></li>
<li><p><em>All</em> your inputs will now be interpreted as Python code.</p></li>
<li><p>Exit with <code class="docutils literal notranslate"><span class="pre">quit()</span></code>.</p></li>
</ul>
</aside>
<p>We can now enter multi-line Python code:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; a = &quot;Test&quot;
&gt; print(f&quot;This is a {a}.&quot;)
This is a Test.
</pre></div>
</div>
<p>Lets try to define a function:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; def hello_world(who, txt):
...
&gt; who.msg(txt)
...
&gt;
[py mode - quit() to exit]
</pre></div>
</div>
<p>Some important things above:</p>
<ul class="simple">
<li><p>Definining a function with <code class="docutils literal notranslate"><span class="pre">def</span></code> means we are starting a new code block. Python works so that you mark the content
of the block with indention. So the next line must be manually indented (4 spaces is a good standard) in order
for Python to know its part of the function body.</p></li>
<li><p>We expand the <code class="docutils literal notranslate"><span class="pre">hello_world</span></code> function with another argument <code class="docutils literal notranslate"><span class="pre">txt</span></code>. This allows us to send any text, not just
“Hello World” over and over.</p></li>
<li><p>To tell <code class="docutils literal notranslate"><span class="pre">py</span></code> that no more lines will be added to the function body, we end with an empty input. When the normal prompt returns, we know we are done.</p></li>
</ul>
<p>Now we have defined a new function. Lets try it out:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; hello_world(me, &quot;Hello world to me!&quot;)
Hello world to me!
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">me</span></code> is still available to us, so we pass that as the <code class="docutils literal notranslate"><span class="pre">who</span></code> argument, along with a little longer
string. Lets combine this with searching for the mirror.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; mirror = me.search(&quot;mirror&quot;)
&gt; hello_world(mirror, &quot;Mirror, Mirror on the wall ...&quot;)
mirror echoes back to you:
&quot;Mirror, Mirror on the wall ...&quot;
</pre></div>
</div>
<p>Exit the <code class="docutils literal notranslate"><span class="pre">py</span></code> mode with</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; quit()
Closing the Python console.
</pre></div>
</div>
</section>
<section id="other-ways-to-test-python-code">
<h2><span class="section-number">3.9. </span>Other ways to test Python code<a class="headerlink" href="#other-ways-to-test-python-code" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">py</span></code> command is very powerful for experimenting with Python in-game. Its great for quick testing.
But you are still limited to working over telnet or the webclient, interfaces that doesnt know anything
about Python per-se.</p>
<p>Outside the game, go to the terminal where you ran Evennia (or any terminal where the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> command
is available).</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">cd</span></code> to your game dir.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code></p></li>
</ul>
<p>A Python shell opens. This works like <code class="docutils literal notranslate"><span class="pre">py</span></code> did inside the game, with the exception that you dont have
<code class="docutils literal notranslate"><span class="pre">me</span></code> available out of the box. If you want <code class="docutils literal notranslate"><span class="pre">me</span></code>, you need to first find yourself:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; import evennia
&gt; me = evennia.search_object(&quot;YourChar&quot;)[0]
</pre></div>
</div>
<p>Here we make use of one of evennias search functions, available by importing <code class="docutils literal notranslate"><span class="pre">evennia</span></code> directly.
We will cover more advanced searching later, but suffice to say, you put your own character name instead of
“YourChar” above.</p>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">[0]</span></code> at the end is because <code class="docutils literal notranslate"><span class="pre">.search_object</span></code> returns a list of objects and we want to
get at the first of them (counting starts from 0).</p>
</div></blockquote>
<p>Use <code class="docutils literal notranslate"><span class="pre">Ctrl-D</span></code> (<code class="docutils literal notranslate"><span class="pre">Cmd-D</span></code> on Mac) or <code class="docutils literal notranslate"><span class="pre">quit()</span></code> to exit the Python console.</p>
</section>
<section id="ipython">
<h2><span class="section-number">3.10. </span>ipython<a class="headerlink" href="#ipython" title="Permalink to this headline"></a></h2>
<p>The default Python shell is quite limited and ugly. Its <em>highly</em> recommended to install <code class="docutils literal notranslate"><span class="pre">ipython</span></code> instead. This
is a much nicer, third-party Python interpreter with colors and many usability improvements.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>pip install ipython
</pre></div>
</div>
<p>If <code class="docutils literal notranslate"><span class="pre">ipython</span></code> is installed, <code class="docutils literal notranslate"><span class="pre">evennia</span> <span class="pre">shell</span></code> will use it automatically.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>evennia shell
...
IPython 7.4.0 -- An enhanced Interactive Python. Type &#39;?&#39; for help
In [1]: You now have Tab-completion:
&gt; import evennia
&gt; evennia.&lt;TAB&gt;
</pre></div>
</div>
<p>That is, enter <code class="docutils literal notranslate"><span class="pre">evennia.</span></code> and then press the TAB key - you will be given a list of all the resources
available on the <code class="docutils literal notranslate"><span class="pre">evennia</span></code> object. This is great for exploring what Evennia has to offer. For example,
use your arrow keys to scroll to <code class="docutils literal notranslate"><span class="pre">search_object()</span></code> to fill it in.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>&gt; evennia.search_object?
</pre></div>
</div>
<p>Adding a <code class="docutils literal notranslate"><span class="pre">?</span></code> and pressing return will give you the full documentation for <code class="docutils literal notranslate"><span class="pre">.search_object</span></code>. Use <code class="docutils literal notranslate"><span class="pre">??</span></code> if you
want to see the entire source code.</p>
<p>As for the normal python interpreter, use <code class="docutils literal notranslate"><span class="pre">Ctrl-D</span></code>/<code class="docutils literal notranslate"><span class="pre">Cmd-D</span></code> or <code class="docutils literal notranslate"><span class="pre">quit()</span></code> to exit ipython.</p>
<div class="admonition important">
<p class="admonition-title">Important</p>
<p>Persistent code</p>
<p>Common for both <code class="docutils literal notranslate"><span class="pre">py</span></code> and <code class="docutils literal notranslate"><span class="pre">python</span></code>/<code class="docutils literal notranslate"><span class="pre">ipython</span></code> is that the code you write is not persistent - it will
be gone after you shut down the interpreter (but ipython will remember your input history). For making long-lasting
Python code, we need to save it in a Python module, like we did for <code class="docutils literal notranslate"><span class="pre">world/test.py</span></code>.</p>
</div>
</section>
<section id="conclusions">
<h2><span class="section-number">3.11. </span>Conclusions<a class="headerlink" href="#conclusions" title="Permalink to this headline"></a></h2>
<p>This covers quite a lot of basic Python usage. We printed and formatted strings, defined our own
first function, fixed an error and even searched and talked to a mirror! Being able to access
python inside and outside of the game is an important skill for testing and debugging, but in
practice you will be writing most your code in Python modules.</p>
<p>To that end we also created a first new Python module in the <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> game dir, then imported and used it. Now lets look at the rest of the stuff youve got going on inside that <code class="docutils literal notranslate"><span class="pre">mygame/</span></code> folder …</p>
</section>
</section>
</div>
</div>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../../../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../../../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="Beginner-Tutorial-Gamedir-Overview.html" title="4. Overview of your new Game Dir"
>next</a> |</li>
<li class="right" >
<a href="Beginner-Tutorial-Tutorial-World.html" title="2. The Tutorial World"
>previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia latest</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../Howtos-Overview.html" >Tutorials and How-Tos</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../Beginner-Tutorial-Overview.html" >Beginner Tutorial</a> &#187;</li>
<li class="nav-item nav-item-3"><a href="Beginner-Tutorial-Part1-Overview.html" >Part 1: What We Have</a> &#187;</li>
<li class="nav-item nav-item-this"><a href=""><span class="section-number">3. </span>Intro to using Python with Evennia</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2023, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>