added venv intro

This commit is contained in:
weygoldt 2024-04-29 14:07:30 +02:00
parent 6424ecaaf5
commit 84fe4b56a3
2 changed files with 141 additions and 10 deletions

View File

@ -5,6 +5,8 @@ to install them, how to upload them, how to maintain them, how to work
with them. For details consult https://packaging.python.org, or
https://py-pkgs.org, or other sites.
Before you create a package please consider building a [virtual
environment](./venv.md) for your project.
## Why packages?
@ -17,12 +19,14 @@ other scripts in the very same directory.
For example, consider a module `addition.py` and a script `analyze.py`
both in the same directory:
```txt
├── addition.py
└── analyze.py
```
In `addition.py` we define a function `add_two()`:
```
def add_two(x):
return x + 2
@ -30,6 +34,7 @@ def add_two(x):
We can use this function in `analyze.py` by importing it from
`addition.py`:
```
from addition import add_two
@ -42,7 +47,6 @@ directory (or if modules are in sub-directories). To make modules
available in other places of your file system or even for other
people, you need to turn the modules into packages.
## Minimal package
First we make a project directory for our new package. Usually the
@ -87,16 +91,20 @@ on your machine and import it from wherever you want.
To install the project, go to the project root, here `packagehowto/` and run
from your shell
```sh
pip3 install .
```
This installs the package of the current project folder `.` somewhere
in your home directory. From anywhere in your home file system you now
can import this package. The import line of our `analyze.py` file
needs to look like this:
```
from numerix.addition import add_two
```
From the addition module of the numerix package the function add_two
is imported.
@ -105,13 +113,14 @@ package, for exmple when you add a new function or when you just fix
some package code. This is tedious, and that is why there is a `-e`
option ("editable install") for `pip install`. So install your package
with
```sh
pip3 install -e .
```
Then all future changes on your package are immediately available
without the need to reinstall the package again.
## The `__init__.py` file
This file is your package. In fact, you could write a package that
@ -119,11 +128,14 @@ only has an `__init__.py` file in the package directory. All code you
want to make available in you package could be placed in the
`__init__.py` file. For example, if you define an `add_four()` function
in `__init__.py` like this:
```
def add_four(x):
return x + 4
```
then it can be imported directly from the package:
```
from numerix import add_four
```
@ -132,34 +144,41 @@ Alternatively, you can define all your functions in module files, like
we did with the function `add_two()` in the `addition.py` module. In
the `__init__.py` file you can import this function and this way make
it available directly from the package. With this line in `__init__.py`
```
from .addition import add_two
```
(note the `.` in front of `addition` - this makes it a relative
import) you can import `add_two()` without specifying the module:
```
from numerix import add_two
```
## Multiple modules within a package
You can have as many modules as you need in your package. Let's add a
module `numbers.py` to the `numerix` package
```txt
└── numerix
├── __init__.py
├── addition.py
└── numbers.py
```
with the following content:
```
from .addition import add_two
def three():
return add_two(1)
```
This makes a function `three()` available that can be imported via
```
from numerix.numbers import three
```
@ -171,7 +190,6 @@ Note, that the `numbers.py` module imports a function from the
And of course you can also import this function in `__init__.py` so
that it can be imported from the package directly.
## Versioning
Your package needs a version number (for details see below). But how to
@ -187,7 +205,6 @@ by a dot. These numbers are incremented in the following way:
- `minor`, when functionality is added in a backwards-compatible manner, and
- `patch`, for backwards-compatible bug fixes.
## Package version
For uploading your package to [PyPi](https://pypi.org/) you need to
@ -233,7 +250,7 @@ file? It would be a very bad idea to write it there directly and
update it whenever you change it in the `__init__.py` file. The
version number should be set only in one place.
This is possible, of course. You need to specify the `version` field
This is possible, of course. You need to specify the `version` field
as `dynamic` in the `[project]` section. This tells the package tool
that the version will be set dynamically by some code. There are
several options to do so. The simplest one is to add a
@ -272,18 +289,21 @@ python3 -m twine upload dist/*
token
## Using `poetry`
You have now seen how you can do everything "from scratch". This is of course
good to know. But there are tools to significantly simplify package creation
and management, such as [`poetry`](https://python-poetry.org/). Its worth
checking it out. Heres a nice demo: https://python-poetry.org/docs/basic-usage/
## Unit tests
pytest
coverage
```sh
pytest -v --cov-report html --cov numerix tests/
```
## Documentation

111
venv.md Normal file
View File

@ -0,0 +1,111 @@
# Why and how to use virtual environments?
## What is a virtual environment?
- A venv is **seperated** from your system packages / software, such as
firefox, thunderbird, etc.
- Packages that are installed cannot talk to system packages and vice versa ->
you know what you use because you have to explicitly install **all** packages
that your project requires.
- They can be build and destroyed easily and quickly to test different versions
of packages (or even python itself!).
## How to build a `venv`?
- PEP405 (=python style guide) virtual environments should be named "venv" or ".venv".
To create one, run:
```sh
python -m venv <name> # e.g. venv or .venv
```
You should now see a new directory in your current working directory called "venv" or ".venv".
To activate it, run this on linux or macos:
```sh
source <name>/bin/activate
```
On windows, you can run
```sh
./<name>/Scripts/Activate.ps1
```
You should now see an indicator in your shell prompt such as:
```sh
(venv) user@host:~/path/to/your/project
```
It is active as long as you do not explicitly deactivate it or close the shell.
You can now `pip install <package>` as you normally would.
To check which python version it uses, you can run this on linux/macos:
```sh
which python3 && which pip
```
Both paths should point to your virtual environment in the project directory.
To deactivate, simply run on linux/macos/windows:
```sh
deactivate
```
What we have now seen all comes with python but there are tools that make this
more convenient: What if you also want to try another pyhton version? Or use
the same venv in multiple projects? For this, there is `pyenv`:
### `venv` pitfalls
- You cannot move or rename **any** directory inside the path to your project
directory or the `venv` breaks. You can rename a folder _inside_ the project
directory as long as you dont change the path to the venv.
- You cannot use the venv for multiple projects
`pyenv` fixes this:
## Using [`pyenv`](https://github.com/pyenv/pyenv.git) / [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv.git)
Use pyenv for managing python versions and pyenv-virtualenv for a slightly
easier way of interacting with venvs.
To download another python version (without destroying your system), simply run:
```sh
pyenv install python3.12
```
To see which versions are installed, you can run
```sh
pyenv versions
```
To set this version as the default in a specific directory (and all its subdirectories), run:
```sh
pyenv local 3.12
```
Now you can either use the tutorial above to create a standard venv or use `pyenv-virtualenv` like this:
```sh
pyenv virtualenv 3.12 <name>
```
Now you can activate it by `pyenv activate <name>` or use it as the standard in the current and subdirectories with
```sh
pyenv local <name>
```
The convenient thing is, that this venv will always be automatically activated
when you enter the directory. If you do this in multiple directories, you can
have the same venv for multiple projects.
There are some alternatives to `pyenv` such as