Python: Difference between revisions

update line numbers referring to snippet
DHCP (talk | contribs)
improve syntax highlighting, prefix shell commands with "$"
Line 59: Line 59:


=== Using Nix shell (new command line) ===
=== Using Nix shell (new command line) ===
nix shell --impure --expr '(import <nixpkgs> {}).python3.withPackages (ps: with ps; [ swh-core swh-scanner ])'
<syntaxhighlight lang="console">
$ nix shell --impure --expr '(import <nixpkgs> {}).python3.withPackages (ps: with ps; [ swh-core swh-scanner ])'
</syntaxhighlight>
If you don't use the channels any more, you can replace <code><nixpkgs></code> by an instance of the <code>NixOS/nixpkgs</code> repository using its absolute path.
If you don't use the channels any more, you can replace <code><nixpkgs></code> by an instance of the <code>NixOS/nixpkgs</code> repository using its absolute path.


Line 179: Line 181:
</syntaxhighlight>
</syntaxhighlight>


==== Using [https://github.com/Mic92/nix-ld nix-ld] ====
==== Using [https://github.com/nix-community/nix-ld nix-ld] ====


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
Line 212: Line 214:
Install with:
Install with:


<syntaxhighlight lang="shell">
<syntaxhighlight lang="console">
nix profile install github:GuillaumeDesforges/fix-python
$ nix profile install github:GuillaumeDesforges/fix-python
</syntaxhighlight>
</syntaxhighlight>


Enter the venv and run:
Enter the venv and run:


<syntaxhighlight lang="shell">
<syntaxhighlight lang="console">
fix-python --venv .venv
$ fix-python --venv .venv
</syntaxhighlight>
</syntaxhighlight>


Line 346: Line 348:
If you use uv it's recommended that you install the Python versions you need using the <code>uv python install</code> command, e.g.
If you use uv it's recommended that you install the Python versions you need using the <code>uv python install</code> command, e.g.


<syntaxhighlight lang="python">
<syntaxhighlight lang="console">
uv python install 3.14 --preview --default
$ uv python install 3.14 --preview --default
</syntaxhighlight>
</syntaxhighlight>


Line 647: Line 649:
In this case use a <code>nix-shell</code> with <code>gobject-introspection</code> and all the libraries you are using (gtk and so on) as <code>buildInputs</code>.
In this case use a <code>nix-shell</code> with <code>gobject-introspection</code> and all the libraries you are using (gtk and so on) as <code>buildInputs</code>.
For example:
For example:
{{Commands|<nowiki>$ nix-shell -p gobjectIntrospection gtk3 'python2.withPackages (ps: with ps; [ pygobject3 ])' --run "python -c \"import pygtkcompat; pygtkcompat.enable_gtk(version='3.0')\""</nowiki>}}
<syntaxhighlight lang=console>
$ nix-shell -p gobjectIntrospection gtk3 'python2.withPackages (ps: with ps; [ pygobject3 ])' --run "python -c \"import pygtkcompat; pygtkcompat.enable_gtk(version='3.0')\""
</syntaxhighlight>


Or, if you want to use matplotlib interactively:
Or, if you want to use matplotlib interactively:
Line 669: Line 673:
In order to use a CPython interpreter built using <code>--with-pydebug</code> during configure phase, override any of the python packages passing <code>enableDebug = true</code> argument:
In order to use a CPython interpreter built using <code>--with-pydebug</code> during configure phase, override any of the python packages passing <code>enableDebug = true</code> argument:


<code>pythonDebug = pkgs.python310.override { enableDebug = true; };</code>
<syntaxhighlight lang=nix>pythonDebug = pkgs.python310.override { enableDebug = true; };</syntaxhighlight>


== Installing Multiple Versions ==
== Installing Multiple Versions ==
Line 693: Line 697:
=== Regression ===
=== Regression ===
With the <code>nixpkgs</code> version of Python you can expect anywhere from a 30-40% regression on synthetic benchmarks. For example:  
With the <code>nixpkgs</code> version of Python you can expect anywhere from a 30-40% regression on synthetic benchmarks. For example:  
<syntaxhighlight lang=python>## Ubuntu's Python 3.8
<syntaxhighlight lang=console>## Ubuntu's Python 3.8
username:dir$ python3.8 -c "import timeit; print(timeit.Timer('for i in range(100): oct(i)', 'gc.enable()').repeat(5))"
username:dir$ python3.8 -c "import timeit; print(timeit.Timer('for i in range(100): oct(i)', 'gc.enable()').repeat(5))"
[7.831622750498354, 7.82998560462147, 7.830805554986, 7.823807033710182, 7.84282516874373]
[7.831622750498354, 7.82998560462147, 7.830805554986, 7.823807033710182, 7.84282516874373]
Line 715: Line 719:
=== My module cannot be imported ===
=== My module cannot be imported ===


If you are unable to do `import yourmodule` there are a number of reasons that could explain that.
If you are unable to do <code>import yourmodule</code> there are a number of reasons that could explain that.


First, make sure that you installed/added your module to python. Typically you would use something like <code> (python3.withPackages (ps: with ps; [ yourmodule ]))</code> in the list of installed applications.
First, make sure that you installed/added your module to python. Typically you would use something like <code> (python3.withPackages (ps: with ps; [ yourmodule ]))</code> in the list of installed applications.
Line 721: Line 725:
It is also still possible (e.g. when using nix-shell) that you aren't using the python interpreter you want because another package provides its own <code>python3.withPackages</code> in buildInputs, for example, yosys. In this case, you should either include that package (or all needed packages) in your withPackages list to only have a single Python interpreter. Or you can change the order of your packages, such that the <code>python3.withPackages</code> comes first, and becomes the Python interpreter that you get.
It is also still possible (e.g. when using nix-shell) that you aren't using the python interpreter you want because another package provides its own <code>python3.withPackages</code> in buildInputs, for example, yosys. In this case, you should either include that package (or all needed packages) in your withPackages list to only have a single Python interpreter. Or you can change the order of your packages, such that the <code>python3.withPackages</code> comes first, and becomes the Python interpreter that you get.


If you packaged yourself your application, make sure to use <code>buildPythonPackage</code> and **not** <code>buildPythonApplication</code> or <code>stdenv.mkDerivation</code>. The reason is that <code>python3.withPackages</code> [https://github.com/NixOS/nixpkgs/blob/91d1eb9f2a9c4e3c9d68a59f6c0cada8c63d5340/pkgs/top-level/python-packages.nix#L57 filters] the packages to check that they are built using the appropriate python interpreter: this is done by verifying that the derivation has a <code>pythonModule</code> attribute and only buildPythonPackage [https://github.com/NixOS/nixpkgs/blob/91d1eb9f2a9c4e3c9d68a59f6c0cada8c63d5340/pkgs/top-level/python-packages.nix#L43 sets this value] (passthru [https://github.com/NixOS/nixpkgs/blob/91d1eb9f2a9c4e3c9d68a59f6c0cada8c63d5340/pkgs/top-level/python-packages.nix#L75 here]) thanks to, notably <code>passthru = { pythonModule = python; }</code>. If you used <code>stdenv.mkDerivation</code> then you can maybe set this value manually, but it's safer to simply use <code>buildPythonPackage {format = "other"; … your derivation …}</code> instead of <code>mkDerivation</code>.
If you packaged yourself your application, make sure to use <code>buildPythonPackage</code> and <b>not</b> <code>buildPythonApplication</code> or <code>stdenv.mkDerivation</code>. The reason is that <code>python3.withPackages</code> [https://github.com/NixOS/nixpkgs/blob/91d1eb9f2a9c4e3c9d68a59f6c0cada8c63d5340/pkgs/top-level/python-packages.nix#L57 filters] the packages to check that they are built using the appropriate python interpreter: this is done by verifying that the derivation has a <code>pythonModule</code> attribute and only buildPythonPackage [https://github.com/NixOS/nixpkgs/blob/91d1eb9f2a9c4e3c9d68a59f6c0cada8c63d5340/pkgs/top-level/python-packages.nix#L43 sets this value] (passthru [https://github.com/NixOS/nixpkgs/blob/91d1eb9f2a9c4e3c9d68a59f6c0cada8c63d5340/pkgs/top-level/python-packages.nix#L75 here]) thanks to, notably <code>passthru = { pythonModule = python; }</code>. If you used <code>stdenv.mkDerivation</code> then you can maybe set this value manually, but it's safer to simply use <code>buildPythonPackage {format = "other"; … your derivation …}</code> instead of <code>mkDerivation</code>.


== See also ==
== See also ==