DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
DevHireLab
Tutorials
BootcampProblemsCode SimulatorAI InterviewSoonContact
Getting Started
01
What is Python and Why Learn It in 2026
02
Installing Python on Windows, Mac, and Linux
03
Setting up VS Code / PyCharm for Python
04
Understanding the Python Interpreter and REPL
05
Writing and Running Your First Python Program
06
Python Syntax and Indentation Rules
Variables and Data Types
01
Variables and Naming Conventions in Python
02
Numbers in Python (int, float, complex)
03
Strings and String Methods in Python
04
Booleans in Python
05
Type Conversion / Casting in Python
06
Understanding the None Type in Python
Operators
01
Arithmetic Operators in Python
02
Comparison Operators in Python
03
Logical Operators in Python
04
Assignment Operators in Python
05
Bitwise Operators in Python
06
Identity (is) and Membership (in) Operators
07
Walrus Operator (:=) in Python
Input, Output & Strings
01
input() and print() Functions in Python
02
f-strings and String Formatting in Python
03
String Slicing and Indexing in Python
04
Common String Methods (split, join, strip, replace)
05
Escape Characters in Python Strings
Control Flow
01
if, elif, else Statements in Python
02
Nested Conditionals in Python
03
for Loops in Python
04
while Loops in Python
05
break, continue, and pass Statements
06
Loop with else Clause in Python
07
match-case (Structural Pattern Matching)
Data Structures
01
Python Lists: Creation, Indexing, Slicing, Methods
02
Python Tuples and Immutability
03
Python Sets and Set Operations
04
Python Dictionaries: Keys, Values, and Methods
05
List Comprehensions in Python
06
Dictionary & Set Comprehensions in Python
07
Working with Nested Lists and Dictionaries
Functions
01
Defining and Calling Functions in Python
02
Function Arguments: Positional, Keyword, Default
03
*args and **kwargs in Python
04
Return Statements in Python Functions
05
Lambda Functions in Python
06
Recursion in Python
07
Variable Scope: Local, Global, Nonlocal
08
Docstrings and Function Annotations
Functional Programming Basics
01
map(), filter(), and reduce() in Python
02
Closures in Python Explained
03
Python Decorators: Basic to Advanced
04
Generators and yield in Python
Object-Oriented Programming (OOP)
01
Classes and Objects in Python
02
The init Constructor in Python
03
Instance vs Class Variables in Python
04
Inheritance in Python (Single, Multiple, Multilevel)
05
Polymorphism in Python
06
Encapsulation in Python
07
Abstraction in Python with the abc Module
08
Magic/Dunder Methods in Python
09
Static and Class Methods in Python
10
The @property Decorator in Python
11
Python Dataclasses Explained
Error Handling
01
try, except, finally in Python
02
Handling Multiple Exceptions in Python
03
Raising Custom Exceptions in Python
04
Understanding Python's Exception Hierarchy
05
Assertions in Python
File Handling
01
Reading and Writing Text Files in Python
02
Working with the with Statement in Python
03
Working with CSV Files in Python
04
Working with JSON Files in Python
05
Working with Directories (os, pathlib) in Python
Modules and Packages
01
Importing Built-in Modules in Python
02
Creating Your Own Modules in Python
03
Understanding Packages and init.py
04
Python Standard Library Overview
05
Installing Packages with pip
Advanced Core Concepts
01
Iterators and Iterables in Python
02
Context Managers in Python (with, contextlib)
03
Multithreading Basics in Python
04
Multiprocessing Basics in Python
05
Asyncio Basics: async/await in Python
06
Memory Management and Garbage Collection in Python
07
Type Hints in Python (typing module)

Installing Packages with pip

Every Python project beyond the basics eventually needs something the standard library doesn't provide — and pip install packages python is how you get it. This article covers pip and virtual environments together, since they're genuinely meant to be used as a pair, plus creating and managing a python requirements.txt file so an entire project's dependencies can be reproduced with one command.

Introduction: What pip Does and Why Virtual Environments Matter

What pip is

pip stands for "Pip Installs Packages" — it's the standard tool for installing third-party Python packages from PyPI, the Python Package Index, the central repository hosting the vast majority of publicly available Python packages.

pip install requests
Why installing globally is risky

If you install packages directly into your system's global Python installation, every project on your machine shares the exact same set of installed packages, at the exact same versions. This becomes a genuine problem the moment two different projects need different, conflicting versions of the same package — Project A needs requests version 2.25, Project B needs requests version 2.31, and a single global installation simply can't satisfy both at once.

The fix: virtual environments

A virtual environment is a self-contained directory holding its own Python interpreter and its own separately installed packages, completely isolated from both your system-wide Python installation and from any other project's virtual environment. Each project gets its own clean, independent set of dependencies, with zero risk of one project's requirements interfering with another's.

Setting Up a Virtual Environment and Basic pip Commands

Creating and activating a venv
# Create a virtual environment named 'venv' (the name is a convention, not a requirement)
python -m venv venv
# Activate it — Windows
venv\Scripts\activate

# Activate it — macOS/Linux
source venv/bin/activate

Once activated, your terminal prompt changes to show the environment's name, typically in parentheses — (venv) — confirming you're now working inside the isolated environment rather than your system's global Python. Always verify this before installing anything. It's an easy step to forget, and installing a package while believing you're inside a virtual environment, when you're actually still on the global Python, is a common, frustrating mistake to trace back later.

Installing a package
pip install requests
Installing a specific version
pip install requests==2.28.1

The == operator pins to an exact version, rather than installing whatever the latest available release happens to be — genuinely important any time you need a guaranteed, specific version, covered in more depth in Section 4.

Verifying installs
pip list
Package         Version
--------------- -------
certifi         2024.2.2
charset-normalizer 3.3.2
idna            3.6
requests        2.28.1
urllib3         2.2.1

pip list shows everything currently installed in the active environment. For detailed information about one specific package:

pip show requests
Name: requests
Version: 2.28.1
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Requires: certifi, charset-normalizer, idna, urllib3
Required-by:

pip show is genuinely useful for quickly checking a package's installed version, its own dependencies (Requires), and what else in your environment depends on it (Required-by).

Managing Dependencies with requirements.txt

What the file is

A requirements.txt file is a plain, simple list of a project's dependencies — one package per line, optionally pinned to exact versions — letting anyone (a teammate, a deployment server, or you, on a different machine) reproduce the exact same environment with a single command.

requests==2.28.1
numpy>=1.20.0
flask
Installing from a requirements.txt
pip install -r requirements.txt

Run this after activating the appropriate virtual environment, and after navigating to the project directory containing the file (pip looks for requirements.txt in your current working directory by default, unless you point it at a different path explicitly). This single command installs every package listed in the file, at whatever version each line specifies.

Generating one from an existing environment
pip freeze > requirements.txt

pip freeze outputs every currently installed package, along with its exact installed version, and > redirects that output directly into a file.

An important caveat: pip freeze captures every package currently installed in the environment — including sub-dependencies your project didn't explicitly choose, but that got pulled in automatically because something you did choose depends on them. If you installed requests, your requirements.txt after running pip freeze will also list certifi, charset-normalizer, idna, and urllib3 — all genuine dependencies of requests itself, even though you never typed pip install certifi yourself. This is generally fine and expected, but it's worth understanding why your requirements file often ends up considerably longer than the list of packages you actually remember installing.

Version Pinning and Specifier Syntax

Exact pinning
requests==2.28.1

Exact pinning (==) guarantees a fully reproducible environment — anyone installing from this file gets precisely this version, with zero ambiguity. This is generally the safest choice for production deployments, where an unexpected version change in a dependency could introduce a bug or a breaking change you weren't prepared for.

Flexible ranges
numpy>=1.18
requests<3.0
numpy>=1.18,<2.0

Flexible version specifiers (>=, <=, <, >, or combinations of them) allow more tolerance — useful when exact reproducibility matters less than allowing minor updates and bug fixes to flow in automatically. numpy>=1.18,<2.0 says "any version from 1.18 up to, but not including, 2.0" — a common pattern for allowing patch and minor updates within a version range you've already confirmed works correctly, while still guarding against a major version bump that might introduce breaking changes.

Beyond PyPI: Git repositories and local paths

Requirements files aren't limited to packages published on PyPI — they can also reference a Git repository directly, or a local file path, for packages that aren't (or aren't yet) published:

git+https://github.com/someuser/somerepo.git@main
./local-packages/my-internal-tool

This is genuinely useful for internal, unpublished packages, or for pulling in a specific unreleased branch or commit of an open-source dependency you need a particular fix from before it's officially released.

Best Practices and Troubleshooting

Always work inside a virtual environment

Reserve global installs for a small handful of genuinely general-purpose command-line tools you want available everywhere, regardless of which project you're currently in (tools like pipx are increasingly the recommended way to handle even that specific case cleanly, keeping each global tool in its own isolated environment automatically). Never use sudo pip install as a habitual fix for a permissions error — that error is almost always a sign you're not actually inside an activated virtual environment as you intended, and forcing the install with sudo just masks the real problem while polluting your system Python further.

Splitting requirements for larger projects

For projects with meaningfully different production and development needs, it's common practice to split dependencies into two files:

# requirements.txt — what's needed to actually run the application
requests==2.28.1
flask==2.3.0
# requirements-dev.txt — additional tools only needed during development
-r requirements.txt
pytest==7.4.0
black==23.7.0
flake8==6.1.0

The -r requirements.txt line inside requirements-dev.txt includes everything from the main file too, so installing from requirements-dev.txt (pip install -r requirements-dev.txt) gives you both the production dependencies and the extra development-only tools, while a production deployment only ever needs to install from the leaner requirements.txt.

Common issues and fixes

"File not found" errors when running pip install -r requirements.txt almost always mean you're in the wrong working directory. Check with ls (macOS/Linux) or dir (Windows) to confirm requirements.txt is actually present in your current directory before troubleshooting anything more complicated.

Dependency version conflicts — pip reporting that two packages require incompatible versions of some shared dependency — usually require adjusting one specific pinned version in your requirements.txt, rather than assuming something is broadly wrong with the whole file. Read the actual conflict message carefully; pip is generally quite explicit about exactly which two requirements are in conflict and why.

Keeping the file current

Whenever you install a new package your project genuinely needs, re-run pip freeze > requirements.txt (or, if you're maintaining a hand-curated file rather than a full freeze, add the new line manually) so the file always accurately reflects your actual, real, currently-working environment. A stale requirements.txt that no longer matches what your project genuinely depends on defeats the entire purpose of having one in the first place — the whole value of the file is that anyone can trust it to reproduce a genuinely working environment, and that trust breaks the moment it falls out of sync with reality.

PREVIOUSNEXT LESSON