Exercises: Libraries and Virtual Environments
These exercises progress from basic environment management through package evaluation and dependency problem-solving. Many exercises involve terminal commands — type them yourself rather than copying.
Difficulty Guide: - ⭐ Foundational (5-10 min each) - ⭐⭐ Intermediate (10-20 min each) - ⭐⭐⭐ Challenging (20-40 min each) - ⭐⭐⭐⭐ Advanced/Research (40+ min each)
Part A: Virtual Environment Basics ⭐
A.1. Create a new directory called venv-practice. Inside it, create a virtual environment named .venv. Activate the environment, verify it's active by checking your prompt and running pip --version (the path it prints should be inside .venv), then deactivate it.
Write down the commands you used for each step (adjusted for your operating system).
A.2. With your virtual environment from A.1 activated, run pip list. In a fresh environment you should see only pip (Python 3.11 and older also add setuptools). Now install the rich library. Run pip list again. How many packages were installed in total? Why is the number greater than 1?
A.3. Still in the same environment, run pip freeze. Compare the output to pip list. What differences do you notice — in format, and in which packages appear? Which command produces output suitable for requirements.txt?
A.4. Deactivate your environment. Run python -c "import rich" (outside the environment). What happens? Activate the environment and run the same command. What happens now? Explain why the results differ.
A.5. Run pip show rich inside your activated environment. Identify:
- The version installed
- The location on disk
- The packages it depends on (the "Requires" field)
Part B: pip and Package Management ⭐-⭐⭐
B.1. Install a specific version of the requests library: version 2.28.0. Then check what version is installed using pip show requests. Now upgrade it to the latest version using pip install --upgrade requests. What version do you have now?
B.2. Run pip freeze > requirements.txt to save your current environment. Open the file and examine its contents. Now uninstall requests using pip uninstall requests. Verify it's gone with pip list. Finally, reinstall everything using pip install -r requirements.txt.
B.3. Look at this requirements.txt file:
requests==2.31.0
flask==3.0.0
pandas>=2.0,<3.0
numpy~=1.26.0
For each line, explain in plain English what version constraint is being applied. Which line is the most restrictive? Which is the most flexible?
B.4. Install the cowsay package (a fun package that makes ASCII art cows say things). Write a two-line Python script that uses it:
import cowsay
cowsay.cow("Virtual environments are awesome!")
Run the script inside your virtual environment to verify it works.
B.5. Explain the difference between pip install requests and pip install requests==2.31.0. When would you use each form?
Part C: Project Setup Practice ⭐⭐
C.1. Create a brand-new project from scratch with proper environment management. Create a directory called weather-app, set up a virtual environment, activate it, install requests, create a requirements.txt, and write a Python script that fetches the current temperature in New York from the free, no-key Open-Meteo API and prints it. Use https://api.open-meteo.com/v1/forecast with the query parameters latitude=40.71, longitude=-74.01 and current=temperature_2m; the temperature is in the response's "current" dictionary.
C.2. Delete the .venv directory from your weather-app project (simulating a fresh clone from version control). Recreate the environment using only the requirements.txt file. Verify your script still works. This demonstrates why requirements.txt matters.
C.3. Create a requirements-dev.txt file for your weather-app project that includes the production requirements plus pytest. Use the -r requirements.txt syntax. Install from the dev file and verify both requests and pytest are installed.
C.4. Write a pyproject.toml file for the weather-app project that includes:
- Project name: "weather-app"
- Version: "0.1.0"
- Description: "A simple current-weather fetcher"
- Requires Python >= 3.13
- Dependencies: requests >= 2.28, < 3.0
- Optional dev dependencies: pytest >= 7.0
Compare the structure to the requirements.txt you created in C.1.
Part D: Package Evaluation ⭐⭐
D.1. Visit pypi.org and look up the requests library. Answer these questions:
- When was the first version released?
- When was the most recent version released?
- How many maintainers does it have?
- What license does it use?
D.2. Now look up a package called python-http-client. Compare it to requests using the evaluation checklist from section 23.6.1. Which would you choose for a new project, and why?
D.3. A classmate recommends installing reqeusts (note the typo). What risk does this pose? What is typosquatting, and how can you protect yourself from it?
D.4. You find two packages that solve the same problem: - Package A: 50,000 weekly downloads, last updated 6 months ago, 200 GitHub stars, MIT license, 3 dependencies - Package B: 500,000 weekly downloads, last updated 2 weeks ago, 5,000 GitHub stars, MIT license, 12 dependencies
Which would you choose? Discuss the trade-offs. Is there a scenario where Package A might be the better choice?
Part E: Diagnosing Problems ⭐⭐-⭐⭐⭐
E.1. You run a script and get this error:
ModuleNotFoundError: No module named 'pandas'
List three possible causes and the diagnostic step you'd take for each one.
E.2. You activate your virtual environment and try to install a package:
(.venv) $ pip install numpy
ERROR: Could not find a version that satisfies the requirement numpy (from versions: none)
ERROR: No matching distribution found for numpy
What might cause this error? List at least two possibilities. (Hint: "from versions: none" means pip found no release it could use at all, so the problem isn't a version pin. Ask yourself why pip might be unable to see, or unable to use, anything on PyPI.)
E.3. A colleague sends you their project. It includes a requirements.txt with this content:
pandas==2.1.4
numpy==1.26.3
matplotlib==3.8.2
tensorflow==2.15.0
Their project worked on their machine, but when you run pip install -r requirements.txt on yours (Python 3.13), pip stops with:
ERROR: Could not find a version that satisfies the requirement tensorflow==2.15.0 (from versions: 2.20.0rc0, 2.20.0, 2.21.0rc0, 2.21.0rc1, 2.21.0, ...)
ERROR: No matching distribution found for tensorflow==2.15.0
a) The package name is spelled correctly and you're online. Look up tensorflow 2.15.0 on PyPI and check which Python versions it supports. What's going on?
b) Your colleague then sends a "fixed" file that pins numpy==2.1.0 instead. On a Python version TensorFlow 2.15 supports, pip now reports ResolutionImpossible. TensorFlow 2.15 declares numpy>=1.23.5,<2.0.0. Explain the conflict in your own words.
c) Propose two different ways to resolve these problems, and say what each one costs.
E.4. Predict what happens in each scenario:
a) You create a virtual environment, install requests, but forget to run pip freeze. You delete the .venv directory and try to recreate the environment.
b) You install packages without a virtual environment on a shared university computer.
c) You commit your entire .venv/ directory to a Git repository and a collaborator on a different operating system clones it.
Part F: Exploration and Research ⭐⭐⭐
F.1. Research the difference between venv, virtualenv, conda, and pipenv. Create a comparison table with columns: tool, who maintains it, when to use it, and key advantage.
F.2. The rich library provides a Progress class for progress bars. Write a script that uses rich.progress.Progress to display a progress bar while simulating a long task (use time.sleep() to simulate work in a loop of 20 iterations).
F.3. Install httpx — a modern alternative to requests that supports async HTTP. Write a script that fetches a URL using httpx and compare its API to requests. How similar are they? Could you switch between them easily?
Part G: Synthesis ⭐⭐⭐-⭐⭐⭐⭐
G.1. Create a complete project called library-explorer that:
- Has its own virtual environment
- Installs requests and rich
- Has a requirements.txt
- Contains a script that takes a list of ten package names (say, the libraries from section 23.5), fetches each one's details from the PyPI JSON API (https://pypi.org/pypi/<package-name>/json), and displays the name, latest version and one-line summary (found under the response's "info" key) in a rich table
G.2. Write a Python script called env_doctor.py that checks the health of your virtual environment. It should:
- Report whether it's running inside a virtual environment (check sys.prefix vs sys.base_prefix)
- List all installed packages and their versions
- Check if a requirements.txt exists in the current directory
- If it exists, compare installed packages against the requirements file and report any mismatches
- Use only standard library modules (no third-party packages needed)
G.3. Research and write a 300-word essay: "Why did Python need virtual environments?" Cover the historical context (Python 2 vs 3 era, system Python on Linux/macOS, the rise of web frameworks that each needed specific library versions). What problem did virtualenv solve before venv was added to the standard library?
Solutions
Appendix: Answers to Selected Exercises does not yet include this chapter. Most problems here check themselves: pip list, pip show and pip check tell you whether an environment looks the way you expect, and running code/example-01-venv-basics.py inside and outside your environment confirms which Python you're using.