Post

21. Virtual Environments and Package Management

Master Python virtual environments and dependency management with venv, pip, Poetry, and best practices for isolated, reproducible project setups.

21. Virtual Environments and Package Management

What we will learn in this post?

  • ๐Ÿ‘‰ Why Virtual Environments?
  • ๐Ÿ‘‰ Creating Virtual Environments with venv
  • ๐Ÿ‘‰ Managing Packages with pip
  • ๐Ÿ‘‰ requirements.txt Best Practices
  • ๐Ÿ‘‰ Introduction to Poetry
  • ๐Ÿ‘‰ conda and Anaconda
  • ๐Ÿ‘‰ Best Practices for Dependency Management

Virtual Environments: Your Projectโ€™s Cozy Workspace ๐Ÿ› ๏ธ

Imagine each of your coding projects as a chef creating a unique dish. Each recipe needs specific ingredients (called dependencies) in exact amounts. If you mix all ingredients from all recipes into one giant kitchen (your global Python installation), things get incredibly messy and conflicting!

๐Ÿคฏ Tackling โ€œDependency Hellโ€

Ever been stuck in โ€œdependency hellโ€? This happens when Project A needs Library X version 1.0, but Project B demands Library X version 2.0. Installing one globally might break the other. Itโ€™s a frustrating conflict!

โœจ Why Virtual Environments are Your Best Friend

Virtual environments (like venv or conda) solve this by creating isolated spaces for each project.

  • ๐Ÿšซ No Conflicts: Each project gets its own, clean set of dependencies. Project A can happily use Library X 1.0 and Project B can use Library X 2.0 side-by-side, without any arguments!
  • โ™ป๏ธ Reproducible Environments: You can easily list your projectโ€™s exact dependencies (e.g., in a requirements.txt file). Anyone can then recreate your exact setup with pip install -r requirements.txt. No more โ€œit works on my machine!โ€ excuses!
  • ๐Ÿงน Clean Global System: Your main Python installation stays neat, free from project-specific clutter.

Hereโ€™s how it generally works:

graph TD
    A["๐Ÿ Python Interpreter"]:::mainPython
    B["๐Ÿ“ฆ Virtual Env<br/>Project A"]:::envA
    C["๐Ÿ“ฆ Virtual Env<br/>Project B"]:::envB
    D["๐Ÿ“š Dependencies<br/>LibX v1.0"]:::depA
    E["๐Ÿ“š Dependencies<br/>LibX v2.0"]:::depB

    A -- "creates" --> B
    A -- "creates" --> C
    B -- "has its own" --> D
    C -- "has its own" --> E
    D -. "Independent" .-> E

    classDef mainPython fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:16px,stroke-width:3px,rx:14
    classDef envA fill:#00bfae,stroke:#005f99,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef envB fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef depA fill:#ff9800,stroke:#f57c00,color:#fff,font-size:14px,stroke-width:2px,rx:10
    classDef depB fill:#ffd700,stroke:#d99120,color:#222,font-size:14px,stroke-width:2px,rx:10

    linkStyle default stroke:#e67e22,stroke-width:3px

This ensures your projects are self-contained, stable, and easy to share.

Hereโ€™s a friendly and visually appealing guide to Python virtual environments!

๐Ÿ“ฆ Python Virtual Environments: Your Projectโ€™s Cozy Corner!

Hey there, fellow coder! Ever had project dependencies clash or different projects needing specific Python versions? ๐Ÿ˜ฉ Pythonโ€™s venv module is your super solution! It creates isolated environments for each project, ensuring your packages stay tidy and conflict-free. Think of it as a separate, clean workspace for every Python adventure! โœจ

๐Ÿ› ๏ธ Creating Your Venv Workspace

Ready to make one? Itโ€™s simple!

  1. Navigate to your project folder in your terminal.
  2. Run this command. Weโ€™ll name our environment myenv (you can choose any name!):

    1
    
    python -m venv myenv
    

    This creates a new folder named myenv within your project, containing an isolated Python installation and its package manager (pip).

๐Ÿš€ Activating Your Environment

Now, letโ€™s step into your new workspace!

๐Ÿ’ป Windows Users

1
myenv\Scripts\activate

๐ŸŽ macOS & Linux Users

1
source myenv/bin/activate

Youโ€™ll see (myenv) prefix in your terminal, indicating itโ€™s active! ๐ŸŽ‰ Now you can pip install packages, and theyโ€™ll only live here.

๐Ÿšช Deactivating Your Environment

Done for the day or switching projects? Easily exit your venv:

1
deactivate

Your terminal prefix will disappear, taking you back to your systemโ€™s global Python.

๐Ÿง  The Venv Flow (Visual Guide)

graph LR
    A["๐Ÿš€ Start Project"]:::start --> B{"๐Ÿค” Need Isolation?"}:::decision
    B -- "Yes" --> C["๐Ÿ“ฆ Create Venv<br/>python -m venv myenv"]:::action
    C --> D{"๐Ÿ”Œ Activate Venv?"}:::decision
    D -- "Windows" --> E["๐Ÿ’ป myenv Scripts activate"]:::windows
    D -- "Mac/Linux" --> F["๐ŸŽ source myenv/bin/activate"]:::unix
    E --> G["๐Ÿ“ฅ Install Packages"]:::install
    F --> G
    G --> H["โš™๏ธ Develop Code"]:::dev
    H --> I{"โœ… Finished?"}:::decision
    I -- "Yes" --> J["๐Ÿšช Deactivate: deactivate"]:::end
    J --> K["๐ŸŒ Back to Global Python"]:::global
    B -- "No" --> K

    classDef start fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef decision fill:#ffd700,stroke:#d99120,color:#222,font-size:16px,stroke-width:3px,rx:14,shadow:6px;
    classDef action fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:14px,stroke-width:3px,rx:14,shadow:6px;
    classDef windows fill:#00bfae,stroke:#005f99,color:#fff,font-size:14px,stroke-width:2px,rx:10,shadow:6px;
    classDef unix fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:14px,stroke-width:2px,rx:10,shadow:6px;
    classDef install fill:#ff9800,stroke:#f57c00,color:#fff,font-size:14px,stroke-width:3px,rx:14,shadow:6px;
    classDef dev fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:14px,stroke-width:3px,rx:14,shadow:6px;
    classDef end fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:14px,stroke-width:3px,rx:14,shadow:6px;
    classDef global fill:#9e9e9e,stroke:#616161,color:#fff,font-size:14px,stroke-width:2px,rx:10,shadow:6px;

    linkStyle default stroke:#e67e22,stroke-width:3px;

Mastering pip: Your Python Package Manager Friend! ๐Ÿš€

Hello, Pythonista! ๐Ÿ‘‹

pip (Pip Installs Packages) is Pythonโ€™s essential tool for managing external libraries. It helps you install, uninstall, and manage Python packages easily. Letโ€™s explore its magic!

1. Installing & Updating Packages pip install ๐Ÿ“ฆ

To add a new library to your project:

  • Basic Install: pip install requests
  • Specific Version: pip install django==3.2 (exact match) or pip install beautifulsoup4>=4.9 (minimum version).
  • From requirements.txt: pip install -r requirements.txt (This file lists all project dependencies).

2. Removing Packages pip uninstall ๐Ÿ‘‹

To clean up a package you no longer need:

  • Simply run: pip uninstall requests

3. Listing Installed Packages pip list ๐Ÿ“ƒ

Want to see whatโ€™s already installed in your environment?

  • pip list displays all packages and their versions.

4. Package Details pip show ๐Ÿ”Ž

Get detailed information about a specific installed package (like its version, location, and dependencies):

  • pip show flask

5. Freezing Dependencies pip freeze ๐ŸงŠ

This command generates a list of all currently installed packages with their exact versions. Itโ€™s perfect for creating a requirements.txt file to share your projectโ€™s dependencies:

  • pip freeze > requirements.txt

6. Finding Packages pip search ๐Ÿ’ก

Looking for a package but donโ€™t know its exact name?

  • pip search "web scraping" searches PyPI (Python Package Index) for packages.


**Visualizing `requirements.txt` Workflow** ๐Ÿ“Š ```mermaid graph TD A["โš™๏ธ Develop Project"]:::dev --> B["๐Ÿ“ฆ Install packages
with pip"]:::install B --> C["๐ŸงŠ Freeze Dependencies
pip freeze > requirements.txt"]:::freeze C --> D["๐Ÿ“ค Share
requirements.txt"]:::share D --> E["๐Ÿ‘ค New User /
๐Ÿš€ Deployment"]:::user E --> F["๐Ÿ“ฅ Install
pip install -r requirements.txt"]:::reinstall F --> G["โœ… Project Ready!"]:::ready classDef dev fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:16px,stroke-width:3px,rx:14 classDef install fill:#ff9800,stroke:#f57c00,color:#fff,font-size:14px,stroke-width:3px,rx:14 classDef freeze fill:#00bfae,stroke:#005f99,color:#fff,font-size:14px,stroke-width:3px,rx:14 classDef share fill:#ffd700,stroke:#d99120,color:#222,font-size:14px,stroke-width:3px,rx:14 classDef user fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:14px,stroke-width:3px,rx:14 classDef reinstall fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:14px,stroke-width:3px,rx:14 classDef ready fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:16px,stroke-width:3px,rx:14 linkStyle default stroke:#e67e22,stroke-width:3px ```


For more in-depth information, always check the official pip documentation.

Your Python Projectโ€™s Essential: requirements.txt ๐Ÿ“ฆ

Ever wondered how to share your Python project so others can run it perfectly? Meet requirements.txt! This simple text file lists all the external libraries your project needs to function. Itโ€™s your projectโ€™s reliable recipe for setting up environments.

Creating & Using Dependencies ๐Ÿš€

To generate this file, simply run pip freeze > requirements.txt. This captures all currently installed packages and their exact versions. To install these dependencies on a new machine or environment, use pip install -r requirements.txt. Easy, right?

Smart Versioning: Pinning & Constraints ๐Ÿ“Œ

Pinning means specifying an exact version, like requests==2.28.1. This ensures everyone uses the identical library version, preventing unexpected issues.

For more flexibility, use version constraints:

  • package==1.2.3: Exactly this version. Ideal for production stability.
  • package>=1.0: Any version 1.0 or newer.
  • package~=1.2.0: Compatible release (e.g., 1.2.x, but not 1.3.0).

Dev vs. Production Dependencies ๐Ÿ› ๏ธ

For larger projects, you often have packages needed only during development (like pytest for testing). Itโ€™s best practice to keep these separate!

  • requirements.txt: For production-critical dependencies.
  • requirements-dev.txt: For development-only tools.
graph TD
    A["๐Ÿ Python Project"]:::project --> B{"๐Ÿ“ฆ Dependencies"}:::decision
    B --> C["๐Ÿš€ Production Deps<br/>requirements.txt"]:::prod
    B --> D["๐Ÿ› ๏ธ Development Deps<br/>requirements-dev.txt"]:::dev
    C --> E["๐Ÿ“ฅ pip install -r<br/>requirements.txt"]:::installProd
    D --> F["๐Ÿ“ฅ pip install -r<br/>requirements-dev.txt"]:::installDev

    classDef project fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:16px,stroke-width:3px,rx:14
    classDef decision fill:#ffd700,stroke:#d99120,color:#222,font-size:16px,stroke-width:3px,rx:14
    classDef prod fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef dev fill:#00bfae,stroke:#005f99,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef installProd fill:#ff9800,stroke:#f57c00,color:#fff,font-size:13px,stroke-width:2px,rx:10
    classDef installDev fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:13px,stroke-width:2px,rx:10

    linkStyle default stroke:#e67e22,stroke-width:3px

Poetry: Your Python Projectโ€™s Smart Companion! ๐Ÿš€

Frustrated with Python dependency management? Meet Poetry, a modern, elegant tool that effortlessly handles dependencies, virtual environments, and project publishing. Think of it as your projectโ€™s intelligent assistant, simplifying your development workflow.

Why Choose Poetry? ๐Ÿค”

Poetry outperforms pip + requirements.txt by offering superior dependency resolution, preventing version conflicts. It goes beyond a basic pyproject.toml, actively using it to manage project metadata and automatically creating a poetry.lock for truly reproducible builds across all environments.

Core Advantages โœจ

  • Conflict-Free: Smartly resolves package versions.
  • Reproducible: poetry.lock ensures consistent setups.
  • Integrated Virtual Environments: Seamless venv management.
  • Streamlined Packaging: Effortless package building and publishing.

Basic Commands ๐Ÿ› ๏ธ

graph TD
    A["๐Ÿš€ Start Project"]:::start --> B["๐Ÿ“ฆ poetry new<br/>my-app"]:::create
    B --> C["โž• Add Dependency"]:::add
    C --> D["๐Ÿ“ฅ poetry add<br/>requests"]:::addCmd
    D --> E["โš™๏ธ Install & Run"]:::install
    E --> F["๐Ÿ“ฆ poetry install"]:::installCmd
    F --> G["โ–ถ๏ธ poetry run<br/>python app.py"]:::run

    classDef start fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:16px,stroke-width:3px,rx:14
    classDef create fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef add fill:#ffd700,stroke:#d99120,color:#222,font-size:14px,stroke-width:3px,rx:14
    classDef addCmd fill:#00bfae,stroke:#005f99,color:#fff,font-size:13px,stroke-width:2px,rx:10
    classDef install fill:#ff9800,stroke:#f57c00,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef installCmd fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:13px,stroke-width:2px,rx:10
    classDef run fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:13px,stroke-width:2px,rx:10

    linkStyle default stroke:#e67e22,stroke-width:3px
  • poetry new my-project
  • poetry add requests (updates pyproject.toml, poetry.lock)
  • poetry install (installs from poetry.lock)
  • poetry run python main.py

Package Manager Comparison Table ๐Ÿ“Š

Choosing the right package manager can significantly impact your development workflow. Hereโ€™s a comprehensive comparison to help you decide:

Featurepip + venvPoetryconda/Anaconda
Dependency ResolutionBasic (may have conflicts)Advanced (solves conflicts)Advanced (cross-platform)
Lock FilesโŒ Manual (requirements.txt)โœ… Automatic (poetry.lock)โœ… Automatic (environment.yml)
Virtual EnvironmentsManual creationAutomatic managementAutomatic management
Non-Python DependenciesโŒ NoโŒ Noโœ… Yes (C libraries, R, etc.)
Project MetadataManual (setup.py)Integrated (pyproject.toml)Manual (environment.yml)
Build & PublishRequires setuptoolsBuilt-inCommunity-focused
SpeedFastModerateSlower (large package index)
Learning CurveLow (standard tool)ModerateModerate-High
Best ForSimple projects, scriptsModern Python projectsData science, scientific computing
InstallationBuilt-in with Pythonpip install poetrySeparate installer
CommunityHuge (default)Growing rapidlyLarge (scientific)
ReproducibilityManual version pinningExcellent (lock file)Excellent (environment export)

๐Ÿ’ก Quick Recommendations

  • Use pip + venv if: Youโ€™re learning Python, working on small scripts, or need simplicity.
  • Use Poetry if: Youโ€™re building modern Python applications, libraries, or want better dependency management.
  • Use conda if: Youโ€™re doing data science, need non-Python dependencies, or work with scientific computing.

Mastering Project Dependencies Like a Pro! ๐Ÿš€

Managing your projectโ€™s ingredients (dependencies) is crucial for smooth sailing. Here are best practices to keep your projects tidy, secure, and reliable, ensuring your software runs perfectly every time.

Core Practices for Happy Projects! ๐ŸŽ‰

Isolate with Virtual Environments ๐ŸŒณ

Always use virtual environments (like venv) to keep project dependencies separate from your system Python. This prevents conflicts and ensures your project runs with its specific package versions. You can create one with python -m venv .venv.

Pin Those Versions! ๐Ÿ“Œ

Specify exact package versions (e.g., requests==2.28.1) in your requirements.txt. This โ€œpinsโ€ dependencies, guaranteeing consistent builds across different environments. Use pip freeze > requirements.txt to capture them.

Separate Dev & Prod Needs ๐Ÿ› ๏ธ๐Ÿš€

Keep development-only packages (like testing tools) in a separate file, often requirements-dev.txt, from production requirements. This keeps your production environment lean and secure, reducing attack surface.

Update & Scan Regularly! โœจ๐Ÿ›ก๏ธ

Regularly update your packages to gain new features, bug fixes, and critical security patches. Integrate security scanning tools (e.g., pip-audit or Snyk) into your workflow to detect vulnerabilities early and fix them.

Document Clearly ๐Ÿ“

Maintain a clear README.md or pyproject.toml describing your projectโ€™s dependencies and how to set up the environment. This helps collaborators understand your project quickly and onboard smoothly.

graph TD
    A["๐Ÿš€ Start Project"]:::start --> B["๐Ÿ“ฆ Create Virtual Env"]:::venv
    B --> C["๐Ÿ“ฅ Install Dev &<br/>Prod Deps"]:::install
    C --> D["๐Ÿ“Œ Pin Dependencies"]:::pin
    D --> E["๐Ÿ“‚ Separate<br/>Prod/Dev Lists"]:::separate
    E --> F["โš™๏ธ Develop & Test"]:::dev
    F --> G{"๐Ÿ”„ Regularly<br/>Update & Scan?"}:::decision
    G -- "Yes" --> C
    G -- "No" --> H["๐Ÿ“ Document<br/>Dependencies"]:::doc
    H --> I["๐Ÿš€ Deploy/Maintain"]:::deploy

    classDef start fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:16px,stroke-width:3px,rx:14
    classDef venv fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef install fill:#ff9800,stroke:#f57c00,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef pin fill:#00bfae,stroke:#005f99,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef separate fill:#43e97b,stroke:#38f9d7,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef dev fill:#6b5bff,stroke:#4a3f6b,color:#fff,font-size:14px,stroke-width:3px,rx:14
    classDef decision fill:#ffd700,stroke:#d99120,color:#222,font-size:14px,stroke-width:3px,rx:14
    classDef doc fill:#9e9e9e,stroke:#616161,color:#fff,font-size:14px,stroke-width:2px,rx:10
    classDef deploy fill:#ff4f81,stroke:#c43e3e,color:#fff,font-size:16px,stroke-width:3px,rx:14

    linkStyle default stroke:#e67e22,stroke-width:3px;

๐ŸŽฎ Try Virtual Environments Live!

๐Ÿš€ Try this Live โ†’ Click to open interactive PYTHON playground

๐ŸŽฎ Try Package Management Operations!

๐Ÿš€ Try this Live โ†’ Click to open interactive PYTHON playground

๐Ÿ’ก Project: Multi-Project Environment Manager - Master Virtual Environment Management (Click to expand)

๐Ÿš€ Your Challenge:

Create a comprehensive Multi-Project Environment Manager - a Python tool that helps you manage multiple Python projects with different virtual environments and dependencies on the same machine. Your system should handle project creation, package installation, dependency tracking, and cross-platform compatibility. ๐Ÿโœจ

๐Ÿ“‹ Requirements:

Part 1: CLI Tool Commands

  • Create a CLI tool (project_manager.py) with these commands:
    • create <project_name> - Creates a new project directory with a virtual environment
    • list - Lists all managed projects and their Python versions
    • activate <project_name> - Generates an activation command for the project's venv
    • install <project_name> <package> - Installs a package in the project's venv
    • freeze <project_name> - Generates requirements.txt for the project
    • status <project_name> - Shows installed packages and their versions

Part 2: Data Management

  • Store project metadata in JSON file (~/.project_manager/projects.json)
  • Track: name, path, Python version, creation date for each project
  • Implement error handling for missing projects or failed operations
  • Use pathlib.Path for cross-platform path handling

Part 3: Cross-Platform Support

  • Detect user's operating system (Windows/Unix)
  • Generate appropriate activation commands for each OS
  • Handle path separators correctly across platforms
  • Use subprocess module to run python -m venv commands

๐Ÿ’ก Implementation Hints:

  • Step 1: Import required modules: import subprocess, json, sys, os and from pathlib import Path
  • Step 2: Create venv: subprocess.run([sys.executable, '-m', 'venv', venv_path])
  • Step 3: Detect OS: if sys.platform == 'win32' for Windows, else Unix
  • Step 4: Store metadata: Use json.dump() and json.load() for persistence
  • Step 5: Install packages: Run pip in venv using subprocess with venv's Python executable
  • Step 6: List packages: Use pip list --format=json or pip freeze
  • Bonus: Add try-except blocks for robust error handling

๐Ÿ“Š Example Input/Output:

# Create a new project
$ python project_manager.py create my_api
โœ… Project 'my_api' created at /Users/dev/projects/my_api
โœ… Virtual environment initialized

# Install packages
$ python project_manager.py install my_api flask requests
๐Ÿ“ฆ Installing flask in my_api...
๐Ÿ“ฆ Installing requests in my_api...
โœ… Packages installed successfully

# Freeze dependencies
$ python project_manager.py freeze my_api
โœ… requirements.txt created at /Users/dev/projects/my_api/requirements.txt

# List projects
$ python project_manager.py list
๐Ÿ“‹ Managed Projects:
  1. my_api (Python 3.11.5) - Created: 2025-12-09
  2. data_processor (Python 3.10.2) - Created: 2025-12-08

# Show status
$ python project_manager.py status my_api
๐Ÿ“Š Project: my_api
๐Ÿ Python: 3.11.5
๐Ÿ“ฆ Installed Packages:
  - flask==3.0.0
  - requests==2.31.0
  - click==8.1.7

๐ŸŽ† Bonus Challenges:

  • Challenge 1: Dependency Conflict Detection - Before installing, check if the package version conflicts with existing dependencies
  • Challenge 2: Environment Comparison - Add a diff <project1> <project2> command to compare installed packages
  • Challenge 3: Bulk Operations - Support install-all <project_name> requirements.txt to install from a file
  • Challenge 4: Interactive Mode - Add a --interactive flag for a menu-driven interface using rich or questionary
  • Challenge 5: Export/Import - Implement export and import commands to backup/restore all project configurations
  • Challenge 6: Virtual Environment Types - Support both venv and conda environment creation

Share Your Solution! ๐Ÿ’ฌ

Built your environment manager? Awesome! Share your approach in the comments below. How did you handle cross-platform compatibility? Did you add any creative features? Let's learn from each other! ๐Ÿš€


๐ŸŽ“ Conclusion

Youโ€™ve now mastered Pythonโ€™s virtual environment and package management ecosystem! From creating isolated environments with venv to managing dependencies with pip, requirements.txt, and modern tools like Poetry, youโ€™re equipped to handle any Python project setup. Remember that proper environment isolation prevents conflicts, pinning versions ensures reproducibility, and choosing the right package manager (pip, Poetry, or conda) depends on your projectโ€™s specific needs. Practice with the hands-on assignment to solidify these concepts, and always keep your dependencies documented and secure for smooth collaboration and deployment! ๐Ÿš€


This post is licensed under CC BY 4.0 by the author.