Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python docs: add an example for a virtualenv and pip through nix-shell #21837

Merged
merged 2 commits into from Jan 18, 2017
Merged

python docs: add an example for a virtualenv and pip through nix-shell #21837

merged 2 commits into from Jan 18, 2017

Conversation

Azulinho
Copy link
Contributor

Motivation for this change

To address:
#66

And to document what actually worked for me while dealing with different python projects that required a virtualenv and compilation of external dependencies.

Things done
  • Tested using sandboxing
    (nix.useSandbox on NixOS,
    or option build-use-sandbox in nix.conf
    on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • Linux
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

@mention-bot
Copy link

@Azulinho, thanks for your PR! By analyzing the history of the files in this pull request, we identified @FRidh, @bennofs and @abbradar to be potential reviewers.

Copy link
Member

@FRidh FRidh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to create a functioning virtualenv on Nix is a recurring question and it's good to address this in the manual.

When including this example it should also describe the limitations of this method. E.g., how are you dealing with packages that have extension types, like numpy?

How do you make sure the paths in the store remain available? Will you add a gc root? And what happens when you nix-shell again but nixpkgs has updated?

Can you use additional packages from Nix? And if so, how do you deal with dependencies between packages in the virtualenv and packages in the store? E.g., you make package a available via Nix, and install b via requirements.txt.


```

th import <nixpkgs> {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 letters missing here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixing it

th import <nixpkgs> {};
with pkgs.python27Packages;

buildPythonPackage {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're not building a Python package, but an environment. I suggest you use python.buildEnv or else I think you might as well use stdenv.mkDerivation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works for me

python27Packages.virtualenv
python27Packages.pip
stdenv
zlib ];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the purpose of all these packages? Are some hard dependencies, or are they just examples of packages?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my particular requirements.txt is for a twisted project which requires a few python modules containing C extensions. The packages listed are the dependencies required to build those particular python modules.

I guess I can expand that block stating which are required (like the virtualenv and pip), and which are related to dependencies of the modules listed in the requirements.txt file.

src = null;
# When used as `nix-shell --pure`
shellHook = ''
unset http_proxy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation of this block

# When used as `nix-shell --pure`
shellHook = ''
unset http_proxy
export GIT_SSL_CAINFO=/etc/ssl/certs/ca-bundle.crt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed, and if so, why?
Maybe also SOURCE_DATE_EPOCH for when you want to build wheels?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad, those are actually only relevant to my own setup. pulling them out...
and adding SOURCE_DATE_EPOCH

@Mic92 Mic92 merged commit a9495b3 into NixOS:master Jan 18, 2017
@Mic92
Copy link
Member

Mic92 commented Jan 18, 2017

Thanks.

@Mic92
Copy link
Member

Mic92 commented Jan 18, 2017

I actually wanted to squash them together, but hit the wrong button...

@CMCDragonkai
Copy link
Member

CMCDragonkai commented Sep 20, 2017

I'm always been confused here. The normal python docs mentions things like withPackages, pkgs.python35Packages.python.buildEnv.override (which do pretty much the same thing) and the only thing they do is create a python with the necessary nix python packages (there's no way to combine it with non-python dependencies?). However you don't actually need this, you can just use a normal shell.nix with all the python dependencies placed into the buildInputs of stdenv.mkDerivation and all of the python packages will be made available to the nix-shell installed python using packageHooks that change the PYTHONPATH variable.

So then the question becomes how does pip interact within a nix-shell. By default it simply doesn't work. I would prefer that pip worked similar to Node's npm or PHP's composer or even Haskell's stack, in that dependencies were installed in the current directory. Unfortunately this is not possible without some hacks into --root or --target or --prefix or --install-option which is quite complex as well.

The only way I've found that actually works is nix-shell (with stdenv.mkDerivation or python35Packages.buildPythonApplication) for system dependencies and python dependencies that I don't want to compile via pip + virtualenv and pip for all the other normal pip dependencies. But I thought that there would be a shellHook or something that would change pip to install into the local directory and thus we wouldn't need an extra virtualenv layer in between nix-shell and pip.

There's also the question of what happens when there's a nix installed python dependency like numpy and a numpy specified in the requirements.txt. When pip runs an installation, does it respect the fact that numpy already exists, or does it check the version requirements and decides to install a local copy, and if it does, does the resulting python find the virtualenv + pip installed one or the nix supplied one?

Finally there's the various python2nix projects that appears to take existing python projects and generate the necessary nix expressions. I'm not sure if any of these ones work well for creating new python packages for submission to nix in a similar vein to node2nix.


I found a way that doesn't require virtualenv. It's a combination of buildPythonApplication and usage of --prefix option in pip. See this: https://gist.github.com/CMCDragonkai/dcc1b538352624ea690d695ee1ff1528#python

# the following packages are related to the dependencies of your python
# project.
# In this particular example the python modules listed in the
# requirements.tx require the following packages to be installed locally
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- requirements.tx
+ requirements.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants