added venv intro
This commit is contained in:
parent
6424ecaaf5
commit
84fe4b56a3
40
README.md
40
README.md
@ -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
111
venv.md
Normal 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
|
Loading…
Reference in New Issue
Block a user