A “Hello, World!” program is a computer program that displays a message similar to “Hello, World!” on the screen/terminal. It illustrate how all surrounding “ecosystem” (such as compilers, interpreters, source files) are used together. It also show some very basic syntax of the programming language. In the high-level language such as Python such programs tend to me small.
We will iterate through the process couple of times and each time I will explain something more about the process.
But before that, we need to get inside the Docker Container where we have preconfigured Python environment. If you don’t have Docker installed please go to previous chapter and install Docker.
Now, open terminal/CMD in your host OS. Type:
docker pull alexberkovich/alpine-python39
{01_docker_pull}
This command will download my docker image from Docker Hub to your host OS.
You will get something like this:
Now, type:
docker run -it alexberkovich/alpine-python39 bash
{02_docker_run}
pwd — printing working directory.
ls -al — list al files in the directory, including hidden, with long description (not only the filename).
cd tmp — change directory to tmp (relative to the cwd=current working dirctory=/)
Note, after login, we’re starting from directory /. When we list all files in that directory we see among the others file tmp. We could write cd /tmp
this uses absolute path and will work from any directory.
Note: These explanation may be not enough for you. Fell free to search about these specific command or for some basic bash tutorial.
Now, use your favorite text editor, for example vi
, but I prefer nano
to create your first program. Type
nano hello.py
{03_nano_hello}
Type:
print("Hello, World!")
{04_hello.py}
Now, click on CTRL+O,
you should see the following screen:
Press enter, now you should at the bottom of your screen the following:
Press CTRL+X
to exit the editor.
Type cat hello.py
to ensure that everything is ok, you should see the following:
First Iteration
So, we have file hello.py
with one line:
print("Hello, World!")
{04_hello.py}
There is so-called “machine language” — the language that computer can understand and run, there is human language, the language that we, humans, communicated, and somewhere in between, there are programming languages such as Assembly, C, C++, Python. Python is not human language, there are sever restriction on how it should be used. Those restriction is done in order that some “translator”/other program be able to “translate” it to the machine language.
In Python, such “translator” is interpreter. His name is python
.The basic usage is the following:
python hello.py
{05_python_hell.py}
Python
interpreter go over the provided file, hello.py, line-by-line and interprets it, making it “executed”.
So, there is only one in the file. It says print to the screen “Hello, World”, so interpreter does exactly this. There are some more details, that I’m skipping here, but I will get back them later.
Second Iteration
Now, let’s run “Hello, world!” in different way. Let’s open interpreter in interactive mode, let’s type:
python
{06_python.py}
Than, let’s type
print("Hello, world!")
{07_print_hello_world.py}
Than, we will get:
Hello, world!
{08_hello_world.py}
on the terminal.
We can also type:
1+1
{09_1_plus_1}
and we will get
2
{10_two}
as expected. In order to quit from interpreter type
quite()
{11_quite}
In interactive mode we can type expression and get immediate feedback.
On other hand, at first approximation running python
with source file is like feeding line-by-line an interactive interpreter. If we will dig deeper, we will found that running python
interpreter with file with source code enables special kind of optimization that helps decrease the time the program is runs. I will talk about it in next chapter.
Jupyter Notebook and others are basically extensions of interactive interpreter. They provide more user-friendly, web-based, modern UI to use, and not CLI as python
does, but in principle they are exactly the same.
You can try it by running docker container as following:
docker run -itp 8888:8888 alexberkovich/alpine-python39 /bin/bash -c "\
conda install jupyter -y --quiet && \
mkdir -p /opt/notebooks && \
jupyter notebook \
--notebook-dir=/opt/notebooks --ip='*' --port=8888 \
--no-browser --allow-root"
{12_jupiter_notebook}
Third iteration
It is crucial to run “Hello, World!” example in text editor, without any IDE-Integrative development environment. In such environment you have text editor, interpreter, debugger, etc in one place. Running the program is easy as clicking on the button. For using this book, you can continue to use text editor or even get the source code and only look on it and run.
Note:
1. Mastering IDE, debugging, etc. is essential for productive work, but it is out of scope for this book.
2. If you want to use IDE with some docker container, I recommend to use PyCharm Proffessional. Another option may be VSCode with Docker Extension. I didn’t try VSCode. Note, that Pycharm Community Edition didn’t have support for Dockers.
This book is accompanied by source code that is store in GitHub.
Of course, you can use Git on your host OS and just copy&paste the content of my file to docker. You even can go the Web and takes content of the files from their. You can always type the code by yourself.
But you don’t have to know how to use Git in order to get the code. Search for “git-hub alex-ber” and than open repository with name IntroCS.
I will provide you set of instructions how you can download the source code. Of course, you can use Git (whether inside Docker container or in host OS) to do it or even to use Web-based view of the repository instead.
Note: In my docker-container I’ve already preinstalled Git.
First of all, we will create directory where we will put the source code. For example,
mkdir -p /opt/project
{13_git1}
It can be any directory you want, but I want to be specific. This command creates-if-not-exists /opt and than /opt/project. Than type:
curl -L https://github.com/alex-ber/IntroCS/archive/refs/tags/1.0.0.tar.gz -o /tmp/1.0.0.tar.gz
{14_git2}
This command download as ZIP file from GitHub the source code as tar.gz file and put it to /tmp. -L, --location — means follow redirects, -o — means redirect output to a provided file name.
Type:
tar -zxvf /tmp/1.0.0.tar.gz -C /opt/project
{15_git3}
This will extract tag.gz file to /opt/project
directory.
To remove tar.gz file type:
rm /tmp/1.0.0.tar.gz
{16_git4}
Than type
cd /opt/project/IntroCS-1.0.0
{17_git4}
Note: You can use
cd/pwd/ls -al
to traverse the source tree. Please read any basic tutorial how to do it. I will show, how to run the-very-first “Hello, world!” program. Optionally you can install Midnight Commander to do this. Just type
apk add --no-cache mc
{18_mc}
So, we’re in IntroCS-* directory. Just type:
cd 02_hello_world/
{19_cd_hello_world}
This is the name of the chapter.
and than, type
python 04_hello.py
{20_python_hello}
You will see “Hello, world!” message on the terminal.
You can go the directory of the chapter that you’re reading and run files from their.
Forth iteration-some theory
Python (and C) is imperative language. What does it means?
Imperative programming is a programming paradigm that uses statements that change a program’s state. In much the same way that the imperative mood in natural languages expresses commands, an imperative program consists of commands for the computer to perform. Imperative programming focuses on describing how a program operates step by step, rather than on high-level descriptions of its expected results. The term is often used in contrast to declarative programming, which focuses on what the program should accomplish without specifying all the details of how the program should achieve the result. In short, program in Python does exactly what we’ve said to do.
No, let’s back to the python
. I’ve said, that this is interpreter, that just read and execute the file with the code line-by-line.
As you’ve see there is division imperative vs declarative. It is not exclusive or, it is rather a range. For example, using regular expressions in the Python, is using declarative approach (but Python, in general, is near the end of the spectrum of imperative language).
If it is your first reading of the book, feel free to skip everything till the end of the chapter. I encourage to read it, if you already know some programming language.
You can safely skip this paragraph. Declarative programming is a non-imperative style of programming in which programs describe their desired results without explicitly listing commands or steps that must be performed. Functional and logical programming languages are characterized by a declarative programming style. In logical programming languages, programs consist of logical statements, and the program executes by searching for proofs of the statements. Logic programming languages such as Prolog state and query relations. The specifics of how these queries are answered is up to the implementation and its theorem prover, but typically take the form of some sort of unification. Make build specification language, Puppet’s configuration management language, regular expressions, and a subset of SQL (SELECT queries, for example). For example, when we write simple SELECT * from sometable, we’re not telling the DB how to provide us with needed data, what steps it should do, we only describe to DB what is expecting result we waned to achieve. With HTML we just describe how we want our web-page look like, but it is the browser that perform specific steps (and sometimes, different browser gives you different results…that is where standardization took place…).
Note: In this book I will consider only implementation of Python, using C, the classic implementation (called CPython or just Python for short). You should know that there are another implementations IronPython — which compiles to CLR codes, i.e., “.NET”, Jython — (which compiles to JVM codes), PyPy (which is written in Python itself).
The other distinction is compiled language vs interpreted language.
Let’s define, what is pure interpreted languages, and pure compiled language and than, we will where Python fits into the picture. Pure interpreted language is like Python-I’ve-been-describe-you — we run the program line-by-line and interpret or execute it.
C is pure compiled language. You can’t write the source code and just execute it (or run it) as you with Python. Computer doesn’t understand C directly (it also doesn’t understand Python directly, it is Python’
s interpreter job to “translate” it to the computer), the way the C-program works, they have addition step — the compilation step.
First, you should run special program, called compiler, to produce “machine code”, then linked with other C files and startup code to create standalone executables. Once the executable is produced, it runs on the machine directly — you don’t need to ship the C compiler you used to produce the program to your user.
An interpreted language like Python, in contrast, requires you to have the interpreter present to run the program, because it’s not run by the machine directly. Instead, it’s run by the interpreter, which typically translates the program into an intermediate thing, called bytecode. Where things get confusing is that interpreted languages also call the built-in or standalone tool that translates source files into bytecode a “compiler”. In standard Python (CPython), a single executable serves as both the source-code “compiler” and as the interpreter of the compiled bytecode (which can sometimes be cached to disk in the form of “pyc” files).
In other languages, such as Java, the compiler and interpreter are separate programs. Java programs are first compiled to Java Virtual Machine bytecode using the “javac” executable, then the compiled java bytecode is run using the “java” executable.
So even though Python is compiled to bytecode in certain cases (e.g., imported packages), the compiled bytecode still can’t be run directly by the machine — it needs an interpreter.
https://codesolid.com/what-are-those-pyc-files-in-a-python-project/
Quote from Python’s documentation:
interpreted
Python is an interpreted language, as opposed to a compiled one, though the distinction can be blurry because of the presence of the bytecode compiler. This means that source files can be run directly without explicitly creating an executable which is then run. Interpreted languages typically have a shorter development/debug cycle than compiled ones, though their programs generally also run more slowly.
…interactive
Python has an interactive interpreter which means you can enter statements and expressions at the interpreter prompt, immediately execute them and see their results. Just launch
python
with no arguments (possibly by selecting it from your computer’s main menu). It is a very powerful way to test out new ideas or inspect modules and packages (rememberhelp(x)
).…
bytecode
Python source code is compiled into bytecode, the internal representation of a Python program in the CPython interpreter. The bytecode is also cached in
.pyc
files so that executing the same file is faster the second time (recompilation from source to bytecode can be avoided). This “intermediate language” is said to run on a virtual machine that executes the machine code corresponding to each bytecode. Do note that bytecodes are not expected to work between different Python virtual machines, nor to be stable between Python releases.…
virtual machine
A computer defined entirely in software. Python’s virtual machine executes the bytecode emitted by the bytecode compiler.
https://docs.python.org/3/glossary.html#term-interpreted
Python compiles the source files into a Python-specific lower-level form (known as “bytecode”), does so automatically when needed (when there is no bytecode file corresponding to a source file, or the bytecode file is older than the source or compiled by a different Python version), usually saves the bytecode files to disk (to avoid recompiling them in the future). OTOH IronPython will typically compile to CLR codes (saving them to disk or not, depending) and Jython to JVM codes (saving them to disk or not — it will use the .class extension if it does save them).
These lower level forms are then executed by appropriate “virtual machines” also known as “interpreters” — the CPython VM, the .Net runtime, the Java VM (aka JVM), as appropriate.
CPython is designed to compile as fast as possible, as lightweight as possible, with as little ceremony as feasible — the compiler does very little error checking and optimization, so it can run fast and in small amounts of memory, which in turns lets it be run automatically and transparently whenever needed, without the user even needing to be aware that there is a compilation going on, most of the time. Java and C# typically accept more work during compilation (and therefore don’t perform automatic compilation) in order to check errors more thoroughly and perform more optimizations. It’s a continuum of gray scales, not a black or white situation, and it would be utterly arbitrary to put a threshold at some given level and say that only above that level you call it “compilation”.
Note: I want to emphases again, that Python again is written in C and Python itself.
This story is part of my new book.