# Simple use case with local Python environment and Pipenv

**URL:** <https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630>\
**Category:** Help\
**Created:** [January 25, 2023, 1:39pm UTC](https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630 "2023-01-25T13:39:55Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![robinbrantley](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.flox.dev/robinbrantley/32/39_2.png) [@robinbrantley](https://discourse.flox.dev/u/robinbrantley)\
**Post date:** [January 25, 2023, 1:39pm UTC](https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630/1 "2023-01-25T13:39:55Z")

</div>

posting with approval on behalf of @mikhail.zholobov as this query could be useful to others as well 🙂

* * *

I have some simple use case with local Python environment and I’d like to see if flox/nix can be useful here.

I have a couple of python scripts which I want to run locally in isolated environment with required Python packages (“xlsx2csv” in particular).  
The scripts themselves are not a package, so I guess there is nothing to “build” there.

==\> 1. Project overview

```auto
$ ls -l
total 32
-rw-r--r--@ 1 legal staff 168 Jan 6 2022 Pipfile
-rw-r--r--@ 1 legal staff 1771 Jan 6 2022 
Pipfile.lock
-rwxr-xr-x@ 1 legal staff 2305 Dec 11 09:47 
my_script_1.py
-rwxr-xr-x@ 1 legal staff 1714 Jan 6 2022 
my_script_2.py

<...>

```

Python env is declared in Pipfile:

```auto
$ cat ./Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
xlsx2csv = "*"

[dev-packages]
autopep8 = "*"

[requires]
python_version = "3.9"

```

==\> 2. How I currently work with it using “pipenv”

```auto
$ cd /path/to/project/dir

$ pipenv shell
$ ./my_script_1.py
$ ./my_script_2.py

```

Is there any way how to do it simpler using flox or nix?  
It would be great if I can get them just as commands/symlinks/etc “my\_script\_1” and “my\_script\_2” available in my shell from anywhere, without a need to cd into the dir.

Thank you!

---

<div class="post-metadata">

**Author:** ![garbas](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.flox.dev/garbas/32/382_2.png) [@garbas](https://discourse.flox.dev/u/garbas)\
**Post date:** [February 9, 2023, 11:53am UTC](https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630/3 "2023-02-09T11:53:29Z")

</div>

Hi @mikhail.zholobov!

`flox` could be used in few ways depending on your level of `nix` knowledge. My favorite way (and also a way that requires the least amount of Nix knowledge, if any) is to use `flox` to provide all the packages you would usually need to use your system package manager.

Lets look at your example and try to create a `flox` environment that will provide correct python version as well as all the system level tools.

## 1. Search for your python version

As I see from your `Pipfile` you are using python 3.9, lets look which version is available in `flox`.

```console
$ nix search python39
python39 - A high-level dynamically-typed programming language
  stable.nixpkgs-flox.python39@3.9.14
  stable.nixpkgs-flox.python39@3.9.15
  stable.nixpkgs-flox.python39@3.9.16
  staging.nixpkgs-flox.python39@3.9.14
  staging.nixpkgs-flox.python39@3.9.15
  staging.nixpkgs-flox.python39@3.9.16
  unstable.nixpkgs-flox.python39@3.9.14
  unstable.nixpkgs-flox.python39@3.9.15
  unstable.nixpkgs-flox.python39@3.9.16

python39Full - A high-level dynamically-typed programming language
  stable.nixpkgs-flox.python39Full@3.9.14
  stable.nixpkgs-flox.python39Full@3.9.15
  stable.nixpkgs-flox.python39Full@3.9.16
  staging.nixpkgs-flox.python39Full@3.9.14
  staging.nixpkgs-flox.python39Full@3.9.15
  staging.nixpkgs-flox.python39Full@3.9.16
  unstable.nixpkgs-flox.python39Full@3.9.14
  unstable.nixpkgs-flox.python39Full@3.9.15
  unstable.nixpkgs-flox.python39Full@3.9.16

```

The difference between `python39` and `python39Full` is that the `Full` package comes with all extra dependencies that you usually want python to come with (eg. openssl, curses, …).

At the time of writing the latest release of python 3.9 (from [python.org](http://python.org)) is `3.9.16` which is what is also available in `flox`. There are also other older versions available.

## 2. Create `flox` environment with python

```console
$ flox install -e py39-pipenv stable.nixpkgs-flox.python39Full
created generation 1

```

We just created a `flox` environment called `py39-env` with python 3.9.

If we don’t specify the exact version `flox` will always choose the latest one.

## 3. Adding `pipenv` to the environment

```console
$ flox search pipenv
pipenv - Python Development Workflow for Humans
  stable.nixpkgs-flox.pipenv@2022.10.12
  stable.nixpkgs-flox.pipenv@2022.11.11
  stable.nixpkgs-flox.pipenv@2022.11.25
  staging.nixpkgs-flox.pipenv@2022.10.25
  staging.nixpkgs-flox.pipenv@2022.11.11
  staging.nixpkgs-flox.pipenv@2022.11.25
  unstable.nixpkgs-flox.pipenv@2022.10.25
  unstable.nixpkgs-flox.pipenv@2022.11.11
  unstable.nixpkgs-flox.pipenv@2022.11.25

$ flox install -e py39-pipenv stable.nixpkgs-flox.pipenv
created generation 2

```

## 4. Using `py39-pipenv` environment

```console
$ flox activate -e py39-pipenv

flox [py39-pipenv default] [rok@cercei:~/tmp]$ ls -la
-rw-r--r-- 1 rok users 196 Feb 9 12:39 Pipfile
-rw-r--r-- 1 rok users 4733 Feb 9 12:37 test.xlsx

flox [py39-pipenv default] [rok@cercei:~/tmp]$ pipenv shell

flox [py39-pipenv default] [rok@cercei:~/tmp]$ xlsx2csv test.xlsx
A1,B1,C1
A2,B2,C2

```

## Final thoughts

So `flox` can be used to provide the correct version of `python`, `pipenv` and any other system package that you might require. After that you activate flox environment and use `pipenv` as you are used to.

Now this is a short way how to start using `flox` today without the need to learn any Nix.

There are also other things you can do with it and I would invite you to [checkout out the documentation](https://floxdev.com/docs/basics/).

And if you have any questions just ask them right here.

---

<div class="post-metadata">

**Author:** ![mikhail.zholobov](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.flox.dev/mikhail.zholobov/32/482_2.png) [@mikhail.zholobov](https://discourse.flox.dev/u/mikhail.zholobov)\
**Post date:** [February 10, 2023, 10:49am UTC](https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630/4 "2023-02-10T10:49:09Z")

</div>

Thank you, @garbas !  
That looks interesting, I’ll try it out.  
Sorry if it sounds like a dumb question, but is there a way to do the same without calling `pipenv shell `?

> It would be great if I can get them just as commands/symlinks/etc “my\_script\_1” and “my\_script\_2” available in my shell from anywhere, without a need to cd into the dir.

Thank you!

---

<div class="post-metadata">

**Author:** ![garbas](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.flox.dev/garbas/32/382_2.png) [@garbas](https://discourse.flox.dev/u/garbas)\
**Post date:** [February 11, 2023, 12:36am UTC](https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630/5 "2023-02-11T00:36:27Z")

</div>

I’ll provide two options for the question:

## Option 1: [Building a custom package](https://floxdev.com/docs/custom-packages/) and publish it to custom channel.

This option would be the more proper way of solving this issue at the moment.

The problem with this option is that it requires substantial knowledge of Nix.

At flox we are aware of this huge mountain users need to climb to be able to package and reuse something with Nix. As I write this we are working on a solution which would make this much more approachable.

Unless you are already familiar with Nix or you want to dive deep into Nix I would advise against this approach.

## Option 2: Use [declarative environments](https://floxdev.com/docs/declarative-environments/).

Please read the tutorial on declarative environments and get familiar with `flox edit` command.

While this option requires you to write Nix, it is far from the level it is required with Option 1. I think it is possible to understand the Nix code below without too many explanations.

For the purpose of the example I’m going to assume few things:

- Your script is something simple (no modules etc..). I’ll call this `my\_script.py

```auto
import sys
import xlsx2csv
xlsx2csv.Xlsx2csv("test.xlsx", outputencoding="utf-8").convert(sys.stdout)

```

- Your project is located in `/path/to/project`.  
This is a path to a folder where `Pipfile` and your scripts are located

Next is to use the `flox edit` command and configure few things in this environment.

```shell
$ flox edit -e custom-scripts
<OPENS AN EDITOR>

```

You should write something like this:

```auto
  1 {
  2 # packages in environment
  3 packages.nixpkgs-flox.python39 = {};
  4 packages.nixpkgs-flox.pipenv = {};
  5
  6 # env variable PROJECT which holds an absolute path to your project
  7 environmentVariables.PROJECT = "/home/rok/tmp";
  8
  9 # alias my-script to run my_script.py
 10 shell.aliases.my-script = "pipenv run python $PROJECT/my_script.py";
 11
 12 # shell hook that gets run when you activate the environment
 13 # we want to ensure pipenv install is always run and dependencies are present
 14 shell.hook = ''
 15 # we also pipe the output to somewhere we can later review if needed
 16 pipenv install >>$PROJECT/env.log 2>&1
 17 '';
 18 }

```

Make sure you save the file, which will update the `custom-scripts` environment.

To run `my-script` you can now do:

```shell
$ flox activate -e custom-scripts

flox [custom-scripts default] $ my-script
A1,B1,C1
A2,B2,C2

```

Now there are some drawback to Option 2, but maybe the tradeoff is worth it.

Hope this helps.

---

<div class="post-metadata">

**Author:** ![robertodr](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.flox.dev/robertodr/32/150_2.png) [@robertodr](https://discourse.flox.dev/u/robertodr)\
**Post date:** [February 15, 2023, 4:08pm UTC](https://discourse.flox.dev/t/simple-use-case-with-local-python-environment-and-pipenv/630/6 "2023-02-15T16:08:54Z")

</div>

I’m trying to do something similar to Option 2, but using poetry, and running into difficulties.  
In order:

- I have a `pyproject.toml`:

```auto
[tool.poetry]
name = "flox_poetry"
version = "0.1.0"
description = ""
authors = ["Me"]

[tool.poetry.dependencies]
python = ">=3.8,<3.11"
numpy = "^1.19"

[tool.poetry.group.dev.dependencies]
pre-commit = "^3"
black = "^22"
mypy = "^0.991"
ruff = "^0.0.241"

[tool.poetry.group.test.dependencies]
pytest = "^7"
pytest-cov = "^4"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

[tool.black]
line-length = 88

[tool.ruff]
line-length = 120

# allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"

# assume Python 3.8
target-version = "py38"

[tool.mypy]
python_version = "3.8"
exclude = [
   # exclude sub-folder of `tests` from type checking
   "tests/*/*.py",
]

[[tool.mypy.overrides]]
ignore_missing_imports = true

[tool.pytest.ini_options]
addopts = [
  "--import-mode=importlib",
]
markers = [
  "slow: mark test as slow (>=1 minute runtime)",
]

```

- I create an environment `flox create -e flox_poetry`
- I run `flox edit -e flox_poetry` such that the contents of the file defining the declarative environment are as follows:

```auto
{
  packages = {
    nixpkgs-flox = {
      python3Full = {};
      poetry = {};
    };
  };

  shell.hook = ''
     echo "Flox Environment"
     poetry install
     poetry shell
  '';
}

```

Running `flox activate -e flox_poetry` shows that poetry is doing its thing and I end up in a poetry shell within the flox shell, as I expect.  
However, `python -c "import numpy"` complains that it can’t load zlib. Adding `zlib = {};` to the `packages.nix-flox` set doesn’t help though.
