What happens when we don't use a virtual environment?
Let’s suppose you are starting a new project at work. You have received and understood your project brief and you’ve already done some planning of your code architecture. You’re now ready to start writing some code!
Let’s go through the steps together. 😊
First, create a projects
directory to house your project repository.
→ mkdir projects ~ → cdprojects/ ~/projects → ls ~/projects
At this point we create a new directory called demo-app
to store code for our project:
~/projects → cd ~/projects/ ~/projects → ls ~/projects → mkdir demo-app ~/projects → cddemo-app/
Create a file called demo.py
with the following contents:
import requests
r = requests.get(‘https://www.example.com’)
print(r.status_code)
Remember that when you visit a website in your browser, and generally when you are asking for or sending information on the web, you are making a request. The request used to retrieve data, such as visiting a website, is called aGET
. The data you retrieve will come accompanied by many different pieces of information, such as status codes, which are used to describe if your request succeeded, failed, or if the device that responded to you cannot brew coffee because it is, in fact, a teapot! (If you want to learn a bit more, follow our course Understanding the Web.)
The snippet of code above does just that: it’s asking for information - retrieving the website www.example.com - and it prints the result of the status code: hopefully200
.
At this point, you can try to run demo.py
as follows:
~/projects/demo-app → pythondemo.py
Depending on a number of factors, the program may, or may not, execute successfully. If the script does execute successfully, the output should look as follows:
~/projects/demo-app → pythondemo.py 200
The 200
status code means that the request to https://www.example.com
has been made successfully.
The script has executed successfully because you have the requests package installed in your global packages. You can view your global Python packages by running pip freeze
.
If the program does not execute successfully, it is likely that the output will look as follows:
~/projects/demo-app → python demo.py Traceback (most recent call last): File "demo.py", line1, in <module> import requests ModuleNotFoundError: No module named 'requests'
You will receive the above output if you do not have requests
installed as a global Python package. You can view your global Python packages by running pip freeze
.
Follow the screencast below if you want to double check that you are up to speed!
Run the App in a Virtual Environment
It is best practice to keep use of Python packages installed globally to an absolute minimum. Instead, as discussed in the previous chapter, we create an environment for each individual project we work on and install packages locally, inside the environment.
To create an environment, use the command python3 -m venv <environment name>
. <Environment name>
can be any valid path, but convention dictates that we normally use env
. I am going to use env
:
~/projects/demo-app → python -m venv env
If you now list the files in the demo-app
directory you will see that you have a created a directory called env:
~/projects/demo-app → ls demo.py env
To activate the environment, run source env/bin/activate
(if you are on Windows the command will be env/Scripts/activate.bat
). At this point, your terminal (depending on which one you are using) will likely prepend your environment name to your command prompt so that you can tell which environment you are using.
~/projects/demo-app → source env/bin/activate (env) ~/projects/demo-app
If you run pip freeze
again you should now see no packages listed. This indicates that there are no packages installed inside your virtual environment. This is the default behavior when you create a virtual environment.
(env) ~/projects/demo-app → pip freeze (env) ~/projects/demo-app
Now, if you try re-running the demo.py
script, it absolutely won’t work, and you should get the following output:
(env) ~/projects/demo-app → python demo.py Traceback (most recent call last): File "demo.py", line 1, in <module> import requests ModuleNotFoundError: No module named 'requests'
</pre>
This is because the requests package is not installed in your virtual environment. Now, install requests with pip
:
(env) ~/projects/demo-app → pip install requests Collecting requests Using cached requests-2.23.0-py2.py3-none-any.whl (58 kB) Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 Using cached urllib3-1.25.9-py2.py3-none-any.whl (126 kB) Collecting idna<3,>=2.5 Using cached idna-2.9-py2.py3-none-any.whl (58 kB) Collecting certifi>=2017.4.17 Using cached certifi-2020.4.5.1-py2.py3-none-any.whl (157 kB) Collecting chardet<4,>=3.0.2 Using cached chardet-3.0.4-py2.py3-none-any.whl (133 kB) Installing collected packages: urllib3, idna, certifi, chardet, requests Successfully installed certifi-2020.4.5.1 chardet-3.0.4 idna-2.9 requests-2.23.0 urllib3-1.25.9
The above command installs the requests
package (along with some dependencies, that you may or may not have cached from previous package installations) into your virtual environment. If you run pip freeze
again you will see that you have requests installed, along with some dependencies:
(env) ~/projects/demo-app → pip freeze certifi==2020.4.5.1 chardet==3.0.4 idna==2.9 requests==2.23.0 urllib3==1.25.9
Now, if you try re-running the demo.py
script, it should be successful:
(env) ~/projects/demo-app → python demo.py 200
Congratulations, you have created and used your first Python virtual environment! 😎
That's great! But what if I want to work on a different project?
You will need to ‘exit’ or ‘deactivate’ your virtual environment using the command deactivate
while your virtual environment is activated. Depending on which terminal you are using, the (env)
prepended to your command prompt should be removed.
(env) ~/projects/demo-app → deactivate ~/projects/demo-app
In the above example, I have deactivated the virtual environment from the project root, but you can actually ‘exit’ or ‘deactivate’ your virtual environment from any directory. For example, if I reactivate my virtual environment, but then navigate up two directories I can still deactivate the virtual environment using the deactivate
command:
~/projects/demo-app → source env/bin/activate (env) ~/projects/demo-app → cd .. (env) ~/projects → cd .. (env) ~ → deactivate ~ →
Exercise
You are working as a marketeer at a sales and marketing agency. Your boss is interested in analyzing the physical distance between potential sales targets. They have been working on setting up the very basics of a Python project over the last few weeks, but now they want you to work on the project. Unfortunately they are out of the office today! They have, however, sent you a script containing what they have been working on so far. Your job is to:
Create a project in your projects folder and put the script inside the new project: p2c2s2_exercise_script.py.
Create a virtual environment.
Run the application (the first time you run it, the application will fail).
Research and install the packages that you think you might need to successfully run the application.
Successfully run the application.
Check Your Work
Watch me go through the exercise:
Let’s Recap!
Now that you have completed this chapter you should be confident with the following tasks:
Understand what problem is occurring if you don’t have the required Python packages installed.
Know when to use global Python packages and when it is preferable to use a virtual environment.
Install and use Python packages inside a virtual environment that you have created.
Now that you can create a virtual environment, let’s branch out and learn to juggle multiple virtual environments.