Python scripting#
Overview#
This section explores intermediate Python topics to improve our technique at specific linux/IoT scripting tasks.
We’ll explore:
Passing terminal arguments to a script
__main__and top-level environmentRunning modules as scripts using
__main__Tip for managing
gpiodependencies
Passing Script Arguments#
It’s possible to pass command line arguments to a Python script directly from your shell:
$ python myscript.py first 2 True
The arguments passed are first, 2 and True .
sys.argv#
The Python sys module provides access to these arguments via sys.argv:
sys.argvis a Python list of arguments.
# myscript.py
print(f"Argument List: {sys.argv}")
Output:
$ python myscript.py first 2 True
Argument List: ['myscript.py', 'first', '2', 'True']
Notice the following:
The first element in the list is the name of the script.
Arguments are available as strings.
Unfortunately, we can’t trust that the user will always pass arguments in the correct order and using appropriate data types. We would still need to parse the arguments and make sure they are valid.
Fortunately, there is a built-in module that can help us do that.
argparse#
argparse
is a built-in module that makes it easy to write user-friendly command-line interfaces.
Once the script defines what arguments are required, argparse will figure out how to
parse those out of
sys.argv. The
argparse
module also automatically generates help and usage messages, and issues errors when users
give the program invalid arguments.
For a basic tutorial of
argparse, see this page.
In its simplest form, argparse must be imported and a parser must be instantiated:
# myscript.py
import argparse
parser = argparse.ArgumentParser()
args = parser.parse_args()
print(args)
However, this will generate an error because we must tell argparse what argument flags and what data types to parse.
$ python myscript.py first 2 True
usage: myscript.py [-h]
myscript.py: error: unrecognized arguments: first 2 True
To “teach” argparse how to parse an argument we use the command parser.add_argument()
# myscript.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("word", type=str)
parser.add_argument("number", type=int)
parser.add_argument("toggle", type=bool)
args = parser.parse_args()
print(args)
print(args.word)
print(args.number)
print(args.toggle)
$ python myscript.py first 2 True
Namespace(word='first', number=2, toggle=True)
first
2
True
Notice how in the example above, all arguments were positional, which makes them mandatory. In other words, the order in which they are passed determines which variable they were being assigned to.
It’s also possible to make arguments optional. In this case, they must be specified with the correct “Flag”.
# myscript.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--word", type=str)
parser.add_argument("--number", type=int)
parser.add_argument("--toggle", type=bool)
args = parser.parse_args()
print(args)
print(args.word)
print(args.number)
print(args.toggle)
$ python myscript.py --word first --number 2
Namespace(word='first', number=2, toggle=None)
first
2
None
argparse References#
Top-level environment#
Why include a if __name__ == "__main__": in your script?
There are two ways of executing Python code. Depending on how the code is executed, the
global string variable __name__ will take one of two values:
If the script is run by the Python interpreter :
__name__has the value of__main__
Importing script as a separate Python module:
__name__has the value of the module name.
Let’s illustrate these two cases below.
TL:DR
Official docs:
Summary discussion at Stackoverflow:
Executing as a Script#
Consider the following script:
# file my_script.py
print("Inside my_script.py, variable `__name__` is: ", __name__)
Executing this file with the Python interpreter:
$ python my_script.py
# Output
# Inside my_script, variable `__name__` is: __main__
Executing as a Module#
Consider a new file:
# file your_script.py
print("Inside your_script.py, variable `__name__` is: ", __name__)
Now modify my_script.py to import your_script.py:
# file my_script.py
import your_script
print("Inside my_script.py, variable `__name__` is: ", __name__)
When a file is imported as a module, it’s top-level code gets executed immediately.
When we execute my_script.py again using the Python interpreter:
$ python my_script.py
# Output
# Inside your_script, variable `__name__` is: your_script
# Inside my_script, variable `__name__` is: __main__
The first print statement came from your_script.py when it was imported by
my_script.py.
Notice how inside your_script.py, the variable __name__ was the file name because it
was being run as a module - from a different script (my_script.py).
Top-level Code#
All of the code that is at indentation level 0 gets executed is called the top-level.
__main__ is the name of the environment where top-level code is run.
If a module is being run as a script (as in mys_cript.py above), then __name__ is
instead set to the string "__main__".
You can test whether your script is being run directly or being imported by something else
by testing what __name__ evaluates to:
# another_script.py
def main():
# Include whatever code here.
if __name__ == "__main__":
main() # Will only run if executing file as a script.