This is a basic attempt to understand modern Python package and environment management using Poetry.
- pyenv
- poetry
- pytest
- python-dotenv
brew install openssl readline sqlite3 xz zlib
brew update
brew install pyenv
echo 'eval "$(pyenv init --path)"' >> ~/.zshrc
# this will give the already installed versions of Python on your system
pyenv versions
# to install a specific version
pyenv install 3.11.1
# to **set a specific version** as global from the available list
pyenv global 3.11.1
➜ ~ python -V
Python 3.11.1
➜ ~ pyenv versions
system
* 3.11.1 (set by /Users/subhranshu/.pyenv/version)
Reference Video - https://www.youtube.com/watch?v=0f3moPe_bhk
Since we have pyenv
, pip
is automatically understood to use which version
pip poetry
export PATH=$PATH:$HOME/.poetry/bin
then hit
source ~/.zshrc
# best practice is to start working on a new terminal after this step
poetry config virtualenvs.prefer-active-python true
poetry config virtualenvs.in-project true
poetry config --list
poetry init
# go through the interactive CLI to generate the "pyproject.toml" file
poetry install
poetry shell
We get something like below. If you notice, the VENV is pointing to the current project directory’s .venv
directory
➜ mypylib poetry shell
Spawning shell within /Users/subhranshu/Desktop/projects/mypylib/.venv
➜ mypylib emulate bash -c '. /Users/subhranshu/Desktop/projects/mypylib/.venv/bin
/activate'
(mypylib-py3.11) ➜ mypylib
import requests
print("hello poetry!!")
response = requests.get('https://jsonplaceholder.typicode.com/todos/1')
response_json = response.json()
print(response_json["title"])
IN THE CLI
(mypylib-py3.11) ➜ mypylib python app.py
hello poetry!!
delectus aut autem
(mypylib-py3.11) ➜ mypylib
poetry new --name pysandbox --src pysandbox
poetry install
This creates the below structure-
➜ pysandbox tree
.
├── README.md
├── poetry.lock
├── pyproject.toml
├── src
│ └── pysandbox
│ └── __init__.py
└── tests
└── __init__.py
4 directories, 5 files
create a .gitignore
file
.venv
.env
**/**/__pycache__/**
*.pyc
Add pytest
for running tests
poetry add pytest --group dev
create a test file test_adder.py
for the src/adder.py
file
import unittest
from pysandbox.adder import add, addBy100
class AdderTest(unittest.TestCase):
def test_add_should_add_two_numbers(self):
a = 20
b = 40
self.assertEqual(add(a, b), 60)
def test_add_by_100_should_add_100(self):
a = 40
b = 80
self.assertEqual(addBy100(a, b), 220)
if __name__ == "__main__":
unittest.main()
poetry add python-dotenv --group dev
create a profile.py
import os
from dotenv import load_dotenv
# load ENV variables using load_dotenv()
load_dotenv()
profile = os.getenv("APP_PROFILE")
print(f"the Python app is for '{profile}'")
create a ENV variable in the .env
file
APP_PROFILE=beginner
RUN the program
(pysandbox-py3.11) ➜ pysandbox git:(main) ✗ python src/pysandbox/profile.py
# output
the Python app is for 'beginner'
(pysandbox-py3.11) ➜ pysandbox git:(main) ✗