Packaging and Environments
Where Python looks for your code and how you hand it to someone else: import machinery, isolated environments and lockfiles, and the artifacts you publish. Import errors and dependency conflicts cost teams days.
part ofPythonoverview, primer and where to startread it →on this pageshowhide
explore
- The Import System34 questions
- Modules and Regular Packages4 questions
- Absolute vs Relative Imports3 questions
- sys.path and sys.modules4 questions
- Circular Imports4 questions
- Script vs Module Execution4 questions
- Implicit Namespace Packages4 questions
- Module-Level __getattr__3 questions
- Importing by String Name4 questions
- Meta Path Finders4 questions
- Environments and Dependencies30 questions
- Interpreter Isolation with venv4 questions
- Installing Packages with pip4 questions
- Pinning, Constraints and Lockfiles5 questions
- All-in-One Project Managers5 questions
- Editable Installs4 questions
- Resolving Version Conflicts4 questions
- Choosing the Right Interpreter4 questions
- Distribution and Library Layout47 questions
- pyproject.toml and Build Backends4 questions
- Wheels vs Source Distributions4 questions
- Entry Points and Console Scripts4 questions
- Publishing to PyPI3 questions
- src Layout vs Flat Layout4 questions
- Public API and Versioning5 questions
- Extras and Dependency Groups4 questions
- manylinux and Platform Tags4 questions
- Package Data and Resources4 questions
- Shipping Type Information3 questions
- Deploying an Application4 questions
- Compiled Extension Wheels4 questions
- Release Targets and Upgrades7 questions
- Declaring a Version Floor4 questions
- Deprecations and Removals3 questions
questions
118 · 4 sectionsIn Python, what is the difference between an absolute import and a relative import?
basics
~20 sAn absolute import spells out the full dotted path from an import root, such as from app.core import config. An explicit relative import starts with dots that count outward from the importing module's own package: from . import config.
What does Python's ImportError 'cannot import name X from partially initialized module' mean?
basics
~10 sTwo modules import each other. Python began running the first one, cached it half-finished, and the second one asked it for a name that has not been defined yet, so the name lookup fails.
What does the if __name__ == "__main__": guard at the end of a Python file do?
basics
~20 sPython sets the module global name to "main" only in the file the interpreter was started with; an imported module gets its dotted import name instead. The guarded block therefore runs on direct execution and is skipped on import.
What distinguishes a Python package from a plain module, and what does __init__.py do?
basics
~20 sA module is one importable unit of code, usually a single .py file. A package is a module that can also contain submodules: a directory whose init.py file is executed as the package's own body when it is first imported.
Why does a Python directory with no __init__.py still import as a package?
basics
~20 sSince Python 3.3 (PEP 420) a directory with no init.py imports as an implicit namespace package: the search path held only matching directories, so Python builds a package that runs no code and whose file is None.
What does `pip install -e .` do that a plain `pip install .` does not?
basics
~20 spip install -e . installs the project in editable mode: site-packages receives a pointer back to your working source tree instead of a copy of it, so a source edit takes effect on the next interpreter start without reinstalling.
Why can `python -m pip install` and a bare `pip install` target different interpreters?
basics
~20 sA bare pip is a script on PATH whose shebang points at whichever interpreter installed it, so PATH order decides where the install lands. python -m pip runs the pip belonging to the interpreter you just named, so the packages land where that interpreter imports from.
Why does pyproject.toml declare dependency ranges while a deployed requirements.txt pins exact versions?
basics
~10 spyproject.toml declares abstract dependencies: the ranges a package can work with, re-resolved at install time. A pinned requirements.txt records one concrete resolution so a particular deployment installs exactly the same versions every time.
What can `pip install` take as a target besides a package name from PyPI?
basics
~20 sBesides a name from an index, pip install accepts a path to a project directory, wheel or sdist, a direct URL, a version-control reference such as git+https at a tag or commit, and -r to read requirement lines from a file.
What does an all-in-one Python project manager add on top of pip and venv?
basics
~20 sIt owns the project end to end: it creates and syncs a project-local virtual environment, resolves the declared dependencies into a lock file, and runs commands inside that environment. pip and venv each do one piece and leave the wiring to you.
What does a `[project.scripts]` entry in pyproject.toml create when the package is installed?
basics
~20 sIt declares a console command. At install time the installer generates a small wrapper in the environment's script directory that imports the named module and calls the named function, so typing the command runs your code.
What does `pip install mypkg[redis]` do, and where is that extra declared?
basics
~20 sIt installs mypkg itself plus the optional dependency set named redis. That set is declared in the project's pyproject.toml under the [project.optional-dependencies] table, where each key is an extra name and its value is a list of requirement strings.
Why does pip compile a package with a C extension from source, and what does that build need?
basics
~20 sBecause no prebuilt wheel matched this machine's interpreter version, ABI and platform, pip fell back to the source archive. Compiling it needs a C compiler and linker, CPython's development headers (Python.h), and the project's declared build backend.
How do you ship a JSON schema file inside your Python package's wheel?
basics
~20 sPut the file inside the importable package directory and declare it as package data in your build backend's configuration. Setuptools needs a package-data entry, or include-package-data together with MANIFEST.in; hatchling and flit ship non-code files under the package by default.
What does a single leading underscore on a Python module or class attribute name mean?
basics
~20 sA single leading underscore marks a name as internal: not part of the public API and free to change without notice. It is a convention, not enforcement — outside code can still import and call it.
What does requires-python in pyproject.toml do when an old interpreter installs your package?
basics
~20 sIt declares the interpreter range the distribution supports, and lands in the built metadata as Requires-Python. An installer filters out releases whose range excludes the running interpreter and resolves to the newest release that still allows it.
How do you use sys.version_info to guard code that only runs on newer Python?
basics
~10 sCompare sys.version_info against a plain tuple, as in sys.version_info >= (3, 12), and put the newer-only import or branch inside that guard. Never parse the sys.version string; tuple comparison is exact, cheap and unambiguous.
How do you make a CI run fail on DeprecationWarning without breaking on third-party ones?
basics
~20 sPromote the category to an error, but scope it. Run the suite with -W ignore::DeprecationWarning -W error::DeprecationWarning:yourpackage, or set PYTHONWARNINGS to the same spec: the later filter is checked first, so only your own code is fatal.
How do you stage a migration off stdlib modules PEP 594 removed before an upgrade?
basics
~20 sDo the diagnosis on the interpreter you are leaving: PEP 387 guarantees two releases of DeprecationWarning, but it is filtered out by default. Surface it, diff your imports against the target's sys.stdlib_module_names, then replace modules one at a time before bumping the interpreter.