So far, only the client side of a web application or website has been covered. However, the bulk of the work is usually done on the server, rather than in the browser. Python is an excellent language to handle the backend of web applications and it is very well supported on Raspberry Pi. Moreover, it is the official programming language suggested by Raspberry Pi Foundation. Apart from web development, Python can also be used to develop desktop and command-line applications or games and to the interface of the Raspberry Pi to the real world. This makes it easy to create a web application to display sensor data, or to control the Raspberry Pi.
Python code can be tested directly by running the python command to enter the Python shell. Within the shell, statements can be entered directly. In order to exit the shell, enter quit()
or press Ctrl + D. To run the code as a proper program, enter it into a file with the .py
extension. The program can then be executed by running python example.py
. However, this is still not ideal.
A shebang, which is the following combination #!
, can be added to the start of a file to indicate which program should parse the file. For example, a file starting with #!/usr/bin/python
will always be executed using Python. In order to make the file executable, you should run chmod +x example.py
. The file can then be launched by simply running ./example.py
as any other executable file.
An excellent resource to learn Python can be found at http://learnpythonthehardway.org/. The official documentation can be accessed through http://docs.python.org/2.7/.
In JavaScript, curly braces were used to group statements, while indentation was added only for readability. Python, on the other hand, relies on indentation to group statements. Most commonly, tabs or multiples of four spaces are used for different indentation levels. Another major difference is the use of semicolons before the start of an indented block. This is demonstrated in the following snippet of code:
if (True): print ("foo")
The fundamental data types are numbers, strings, lists, tuples, and dictionaries. Each of these can be assigned as follows:
a = 3.14 b = "foo" c = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") d = ["Bread","Milk","Eggs","Tomatoes"] e = {"James Stewart":2025550193, "Patricia Rayborn":2025550118}
Note that Python does not require a keyword to identify the variable type or to signify variable declaration. A variable set to a certain data type can be assigned a value of another data type later on.
The variable a
is assigned the number 3.14
. In order to convert an object to a string, the str
function can be used. For example, a = str(a)
would convert the variable a
from a number to a string.
In order to assign a string to a variable, either single or double quote marks can be used. Strings can be concatenated (combined) using the +
operand. If the string itself requires a quote mark, the escape character can be used. For example,
"The value of b is "" + b + """
will translate to The value of b is "foo". Apart from using the escape character for quote marks, it may be used to start a new line (
), add a tab (
), or any other character. Since a string is an array of characters, individual characters of string can be indexed with square brackets. A range can be specified with the start and end character indices separated by a colon. For example, b[0]
and b[1:2]
will return f and oo, respectively.
The variable c
is assigned a tuple value. Tuples are immutable lists, that is, they cannot have their values modified. The tuple elements may consist of any combination of data types, including other tuples. Similar to strings and other arrays, each element can be indexed as before.
Standard lists are similar to tuples, but the elements can be sorted, inserted, or removed. The following code will sort the list d
, remove the element Eggs
and insert it back to its original position:
d.sort () d.remove ('Eggs') d.insert (2, 'Eggs')
Tuples are faster than lists and should be used where the elements can remain static. As shown in the preceding example, a constant sequence, such as the days in a week, are better suited to a tuple. However, a shopping list would need to be modified, so a list is preferred.
Finally, dictionaries are similar to lists, but are accessed by a key rather than an index number. For example, e['James Stewart']
will return 202555019, but e[0]
will return an error. In order to check if an element exists in the dictionary, the in
keyword can be used, as shown here:
'foo' in e False 'Patricia Rayborn' in e True
Finally, the tuple, list, and dictionary values can be functions. Dictionaries are particularly useful here as they allow the value of a variable to determine which function to execute.
Decorators allow functions to be extended and are used as follows:
def foo (func): print ("foo") return func @foo def bar (): print ("bar") bar()
The function foo
takes another function as an argument, prints foo, and then returns the given function. The bar
function simply prints bar, but the foo
decorator is added with the @
keyword. Whenever bar
is called, it is passed as the parameter to foo
. As a result, calling bar
prints both foo and bar.
An example where this is useful could be as a range check to ensure that values passed to a function are valid where multiple functions require the same check. Without a range check decorator, each function would require the same snippet of code.
A set of functions can be saved to a file and then imported into another script. The filename, without the extension, is used as the module name. Once a module has been imported, Python searches for it in the current directory, with the directories listed in the PYTHONPATH environment variable and a set of other directories that are dependent on the particular installation.
Modules are imported using the import
keyword. For example, the os
module provides functions to interface with the operating system. The following snippet of code will import the os
module and display the current working directory:
import os print (os.getcwd())
Alternatively, the from
keyword can be used so that the module does not have to be specified once a function has been called:
from os import getcwd print (getcwd())
Flask provides a convenient way to use Python for web development. To demonstrate the basics, it will be used to extend the calculator example by providing a backend if JavaScript is not available.
Before getting started with Flask, it must be installed with the following command:
# apt-get install python-flask
Next, create a directory to store the Flask application and then two subdirectories named static
and templates
as shown:
$ mkdir –p ~/hello/static $ mkdir ~/hello/templates
You should then move the HTML file into the templates directory and the CSS and JavaScript files into the static
folder.
In the new directory, create a hello.py
file with the following content:
#!/usr/bin/python from flask import Flask, request, render_template app = Flask(__name__) @app.route('/') def hello(): try: num1_string = request.args.get('num1') num2_string = request.args.get('num2') number1 = (float(num1_string) if '.' in num1_string else int(num1_string)) number2 = (float(num2_string) if '.' in num2_string else int(num2_string)) result = number1 * number2 return render_template('hello.html', num1 = number1, num2 = number2, result = result) except: return render_template('hello.html') if __name__ == '__main__': app.debug = True app.run(host = '0.0.0.0')
You can then make the file executable by running chmod +x hello.py
.
The file introduces a few new concepts, but most of it should be familiar. The shebang (#!
) ensures that the file is interpreted using the Python binary. Following this, the necessary functions from the Flask module are imported.
__name__
is a global variable within Python that contains the module name. When the script is executed directly, rather than from another script, the __name__
value is __main__
. Before using Flask, the application object needs to be created, which takes the __name__
global variable as the argument.
The application object's route function is used as a decorator to register functions to a URL. For example, if the pi's IP is 192.168.1.101, then @app.route('/')
binds the hello
function to the address http://192.168.1.101/
.
The next new concept is exception handling using the try
and except
statements. When they are encountered, Python tries to execute the try
clause. If no exceptions occur, the except
clause is skipped. Otherwise, the rest of the try
clause is skipped and the except
clause is executed instead.
The request.args.get()
function is used to receive the arguments passed by the GET request. Unfortunately, it returns a string, rather than a float or integer and Python cannot multiply strings. Since the entered number could be an integer or a float, the int
or float
function is used to convert the string depending on whether a decimal point is present in the string. If the GET request does not contain the num1
and num2
parameters, trying to make the conversion will throw an exception.
The line number1 = (float(num1_string) if '.' in num1_string else int(num1_string))
can be rewritten as follows:
if '.' in num1_string: number1 = float(num1_string) else: number1 = int(num1_string)
After both numbers have been converted, multiplied, and assigned to the result
variable, the page itself is returned. The render_template
function takes a filename as an argument along with optional variables, finds the file in the templates directory, and returns the page after processing it. If an error occurs while processing the number inputs, the page is rendered without passing any parameters.
Flask comes with a simple web server that is useful for development. If the file is run as a script directly, the server is launched using the application object's run
function. Passing host='0.0.0.0'
as the argument ensures that the server accepts connections from external IP addresses. Setting app.debug
to True
will display debug information about any errors that occur on the page. These features should not be used on a production server and are only useful for development. A typical server will load the Flask application as a module rather than run it directly, so the lines are inside an if __name__ == '__main__'
clause. This ensures that when the application is deployed, it works and is less vulnerable to attack.
Before the application is properly functional, the HTML template file needs to be modified.
The static files are now no longer found where they were. By default, they are within the static
folder. However, Flask can be configured in many different ways. For example, hello.css
is now found in static/hello.css
, but it could be in any arbitrary folder. To handle this, the url_for
function is used. It is generally used to return the URL for a function. For example, url_for('index')
would return /
. However, when static
is used as the function, it can be used to return the URL for a file when the filename
parameter is passed.
The double curly brackets are used to ensure the content is not considered as typical HTML. You should modify the line that links in hello.css
as follows:
<link rel="stylesheet" href="{{ url_for('static', filename='hello.css') }}" type="text/css">
Next, make sure that the num1
and num2
variables passed by the hello
function to render_template
are displayed in the input boxes:
<p><input name="num1" type="number" value="{{ num1 }}"> * <input name="num2" type="number" value="{{ num2 }}"> =
Finally, you can display the result:
<span id="result">{{ result }}</span></p>
In order to launch the application, run ./hello.py
. Note that the default port for the test server is 5000, so in order to access the application, enter the IP of Raspberry Pi, followed by :5000
. Disabling JavaScript in your browser will show the fallback method working.
For further information about Flask, you can consult the official documentation at http://flask.pocoo.org/docs/.
18.224.58.140