### How to consume Python modules using pip in a virtual environment like I am used to on other Operating Systems? {#how-to-consume-python-modules-using-pip-in-a-virtual-environment-like-i-am-used-to-on-other-operating-systems}
While this approach is not very idiomatic from Nix perspective, it can still be
useful when dealing with pre-existing projects or in situations where it's not
feasible or desired to write derivations for all required dependencies.
This is an example of a `default.nix` for a `nix-shell`, which allows to consume
a virtual environment created by `venv`, and install Python modules through
`pip` the traditional way.
Create this `default.nix` file, together with a `requirements.txt` and
execute `nix-shell`.
```nix
with import <nixpkgs> { };
let
pythonPackages = python3Packages;
in
pkgs.mkShell rec {
name = "impurePythonEnv";
venvDir = "./.venv";
buildInputs = [
# A Python interpreter including the 'venv' module is required to bootstrap
# the environment.
pythonPackages.python
# This executes some shell code to initialize a venv in $venvDir before
# dropping into the shell
pythonPackages.venvShellHook
# Those are dependencies that we would like to use from nixpkgs, which will
# add them to PYTHONPATH and thus make them accessible from within the venv.
pythonPackages.numpy
pythonPackages.requests
# In this particular example, in order to compile any binary extensions they may
# require, the Python modules listed in the hypothetical requirements.txt need
# the following packages to be installed locally:
taglib
openssl
git
libxml2
libxslt
libzip
zlib
];
# Run this command, only after creating the virtual environment
postVenvCreation = ''
unset SOURCE_DATE_EPOCH
pip install -r requirements.txt
'';
# Now we can execute any commands within the virtual environment.
# This is optional and can be left out to run pip manually.
postShellHook = ''
# allow pip to install wheels
unset SOURCE_DATE_EPOCH
'';
}
```
In case the supplied venvShellHook is insufficient, or when Python 2 support is
needed, you can define your own shell hook and adapt to your needs like in the
following example:
```nix
with import <nixpkgs> { };
let
venvDir = "./.venv";
pythonPackages = python3Packages;
in
pkgs.mkShell rec {
name = "impurePythonEnv";
buildInputs = [
pythonPackages.python
# Needed when using python 2.7
# pythonPackages.virtualenv
# ...
];
# This is very close to how venvShellHook is implemented, but
# adapted to use 'virtualenv'
shellHook = ''
SOURCE_DATE_EPOCH=$(date +%s)
if [ -d "${venvDir}" ]; then
echo "Skipping venv creation, '${venvDir}' already exists"
else
echo "Creating new venv environment in path: '${venvDir}'"
# Note that the module venv was only introduced in python 3, so for 2.7
# this needs to be replaced with a call to virtualenv
${pythonPackages.python.interpreter} -m venv "${venvDir}"
fi
# Under some circumstances it might be necessary to add your virtual
# environment to PYTHONPATH, which you can do here too;
# PYTHONPATH=$PWD/${venvDir}/${pythonPackages.python.sitePackages}/:$PYTHONPATH
source "${venvDir}/bin/activate"
# As in the previous example, this is optional.
pip install -r requirements.txt
'';
}
```
Note that the `pip install` is an imperative action. So every time `nix-shell`
is executed it will attempt to download the Python modules listed in
requirements.txt. However these will be cached locally within the `virtualenv`
folder and not downloaded again.
### How to override a Python package from `configuration.nix`? {#how-to-override-a-python-package-from-configuration.nix}
If you need to change a package's attribute(s) from `configuration.nix` you could do:
```nix
{
nixpkgs.config.packageOverrides = super: {
python3 = super.python3.override {
packageOverrides = python-self: python-super: {