mirror of
https://codeberg.org/mhwombat/nix-book.git
synced 2025-12-27 00:34:58 +08:00
261 lines
7.4 KiB
Text
261 lines
7.4 KiB
Text
= Python
|
|
|
|
Start with an empty directory and create a git repository.
|
|
|
|
....
|
|
$ mkdir hello-python
|
|
$ cd hello-python
|
|
$ git init
|
|
....
|
|
|
|
== A simple Python program
|
|
|
|
Next, we'll create a simple Python program.
|
|
|
|
////
|
|
$ curl https://codeberg.org/mhwombat/hello-flake-python/raw/branch/main/hello.py --silent --output hello.py
|
|
////
|
|
|
|
[source,python,linenums]
|
|
.hello.py
|
|
....
|
|
$# cat hello.py
|
|
....
|
|
|
|
== Running the program manually (optional)
|
|
|
|
[NOTE]
|
|
====
|
|
In this section you will learn how to do some development tasks manually, the "hard" way.
|
|
This can help you understand the distinction between Nix's role and
|
|
the Python build system you've chosen.
|
|
Also, if you have a build problem but you're not sure if the fault is in
|
|
your flake definition or some other configuration file,
|
|
these commands can help you narrow it down.
|
|
But you may wish to skip to the <<_configuring_setuptools,next section>>
|
|
and come back here later.
|
|
====
|
|
|
|
Before we package the program, let's verify that it runs. We're going to
|
|
need Python. By now you've probably figured out that we can write a
|
|
`flake.nix` and define a development shell that includes Python. We'll
|
|
do that shortly, but first I want to show you a handy shortcut. We can
|
|
launch a _temporary_ shell with any Nix packages we want. This is
|
|
convenient when you just want to try out some new software and you're
|
|
not sure if you'll use it again. It's also convenient when you're not
|
|
ready to write `flake.nix` (perhaps you're not sure what tools and
|
|
packages you need), and you want to experiment a bit first.
|
|
|
|
The command to enter a temporary shell is
|
|
|
|
`nix shell -p __installables__`
|
|
|
|
Where __installables__ are flakes and other types of packages that you need.
|
|
(You can learn more about these in the
|
|
https://nix.dev/manual/nix/stable/command-ref/new-cli/nix#installables[Nix manual].)
|
|
|
|
Let's enter a shell with Python so we can test the program.
|
|
|
|
[#python-nix-shell]
|
|
....
|
|
$# echo '$ nix shell nixpkgs#python3'
|
|
$# nix shell nixpkgs#python3 --command sh
|
|
$ python hello.py
|
|
....
|
|
|
|
== Configuring setuptools
|
|
|
|
Next, configure the package. We'll use Python's
|
|
setuptools, but you can use other build tools. For more information on
|
|
setuptools, see the
|
|
https://setuptools.pypa.io/en/latest/index.html[Setuptools documentation], especially the section on
|
|
https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html[pyproject.toml].
|
|
|
|
////
|
|
$ curl https://codeberg.org/mhwombat/hello-flake-python/raw/branch/main/pyproject.toml --silent --output pyproject.toml
|
|
////
|
|
|
|
[source,toml,linenums]
|
|
.pyproject.toml
|
|
....
|
|
$# cat pyproject.toml
|
|
....
|
|
|
|
== Building the program manually (optional)
|
|
|
|
[NOTE]
|
|
====
|
|
In this section you will learn how to do some development tasks manually, the "hard" way.
|
|
This can help you understand the distinction between Nix's role and
|
|
the Python build system you've chosen.
|
|
Also, if you have a build problem but you're not sure if the fault is in
|
|
your flake definition or some other configuration file,
|
|
these commands can help you narrow it down.
|
|
But you may wish to skip to the <<python-flake,next section>>
|
|
and come back here later.
|
|
====
|
|
|
|
We won't write `flake.nix` just yet.
|
|
First we'll try building the package manually.
|
|
(If you didn't run the `nix shell` command from <<python-nix-shell,earlier>>, do so now.)
|
|
....
|
|
$ python -m build # Fails
|
|
....
|
|
|
|
The missing module error happens because we don't have `build` available
|
|
in the temporary shell. We can fix that by adding "`build`" to the
|
|
temporary shell. When you need support for both a language and some of
|
|
its packages, it's best to use one of the Nix functions that are
|
|
specific to the programming language and build system. For Python, we
|
|
can use the `withPackages` function.
|
|
|
|
....
|
|
$# echo '$ nix-shell -p "python3.withPackages (ps: with ps; [ build ])"'
|
|
$# nix-shell -p "python3.withPackages (ps: with ps; [ build ])" --command sh
|
|
....
|
|
|
|
Note that we're now inside a temporary shell inside the previous
|
|
temporary shell! To get back to the original shell, we have to `exit`
|
|
twice.
|
|
Alternatively, we could have done `exit` followed by the
|
|
second `nix-shell` command.
|
|
|
|
....
|
|
$# echo '$ python -m build'
|
|
$# python -m build > /dev/null 2>&1
|
|
....
|
|
|
|
After a lot of output messages, the build succeeds.
|
|
|
|
[#python-flake]
|
|
== The Nix flake
|
|
|
|
Now we should write `flake.nix`.
|
|
We already know how to write most of the flake from the examples we did earlier.
|
|
The two parts that will be different are the development shell and the package builder.
|
|
|
|
Let's start with the development shell. It seems logical to write
|
|
something like the following.
|
|
|
|
....
|
|
devShells = forAllSupportedSystems (system:
|
|
let
|
|
pkgs = nixpkgsFor.${system};
|
|
pythonEnv = pkgs.python3.withPackages (ps: [ ps.build ]);
|
|
in {
|
|
default = pkgs.mkShell {
|
|
packages = [ pythonEnv ];
|
|
};
|
|
});
|
|
....
|
|
|
|
Note that we need the parentheses to prevent `python.withPackages` and
|
|
the argument from being processed as two separate tokens. Suppose we
|
|
wanted to work with `virtualenv` and `pip` instead of `build`. We could
|
|
write something like the following.
|
|
|
|
....
|
|
devShells = forAllSupportedSystems (system:
|
|
let
|
|
pkgs = nixpkgsFor.${system};
|
|
pythonEnv = pkgs.python3.withPackages (ps: [ ps.virtualenv ps.pip ]);
|
|
in {
|
|
default = pkgs.mkShell {
|
|
packages = [ pythonEnv ];
|
|
};
|
|
});
|
|
....
|
|
|
|
For the package builder, we can use the `buildPythonApplication`
|
|
function.
|
|
|
|
....
|
|
packages = forAllSupportedSystems (system:
|
|
let pkgs = nixpkgsFor.${system}; in rec {
|
|
hello-flake-python = pkgs.python3Packages.buildPythonApplication {
|
|
name = "hello-flake-python";
|
|
pyproject = true;
|
|
src = ./.;
|
|
build-system = with pkgs.python3Packages; [ setuptools ];
|
|
};
|
|
});
|
|
....
|
|
|
|
If you put all the pieces together, your `flake.nix` should look
|
|
something like this.
|
|
|
|
////
|
|
$ curl https://codeberg.org/mhwombat/hello-flake-python/raw/branch/main/flake.nix --silent --output flake.nix
|
|
////
|
|
|
|
[source,nix,linenums]
|
|
.flake.nix
|
|
....
|
|
$# cat flake.nix
|
|
....
|
|
|
|
== Building the program
|
|
|
|
Let's try out the new flake.
|
|
|
|
....
|
|
$ nix build # Fails
|
|
....
|
|
|
|
Nix flakes only "`see`" files that are part of the repository.
|
|
We need to add all of the important files to the
|
|
repo before building or running the flake.
|
|
|
|
....
|
|
$ git add flake.nix setup.py hello.py
|
|
$ nix build
|
|
....
|
|
|
|
We'll deal with those warnings later.
|
|
The important thing for now is that the build succeeded.
|
|
|
|
== Running the program
|
|
|
|
Now we can run the program.
|
|
|
|
....
|
|
$ nix run
|
|
....
|
|
|
|
By the way, we didn't need to do `nix build` earlier.
|
|
The `nix run` command will first build the program for us if needed.
|
|
|
|
We'd like to share this package with others, but first we should do some
|
|
cleanup.
|
|
It's time to deal with those warnings.
|
|
When the package was built, Nix created a `flake.lock` file.
|
|
We need to add this to the repo, and commit all important files.
|
|
|
|
....
|
|
$ git add flake.lock
|
|
$ git commit -a -m 'initial commit'
|
|
....
|
|
|
|
You can test that your package is properly configured by going to
|
|
another directory and running it from there.
|
|
|
|
....
|
|
$ cd ..
|
|
$ nix run ./hello-python
|
|
....
|
|
|
|
If you move the project to a public repo, anyone can run it. Recall from
|
|
the beginning of the tutorial that you were able to run `hello-flake`
|
|
directly from my repo with the following command.
|
|
|
|
....
|
|
nix run "git+https://codeberg.org/mhwombat/hello-flake"
|
|
....
|
|
|
|
Modify the URL accordingly and invite someone else to run your new
|
|
Python flake.
|
|
|
|
////
|
|
Good adoc0 scripts clean up after themselves.
|
|
$ rm -rf hello-python # clean up
|
|
////
|