Open samuela opened 2 years ago
Update this is reproducible even after deleting ~/.julia/conda
Installing Conda.jl does not actually install the distro — that only happens when a user, or a package like PyCall, first requests that something be installed. e.g. try:
import Conda
Conda.add("numpy")
That being said, it shouldn't need to install Conda at all — by default on Unix, PyCall tries to use the system Python, and apparently that is failing. What happens if you try
python3 -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('VERSION'))"
in your terminal?
I get
[nix-shell:~/dev/research/julia/permuted_sgd]$ python3 -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('VERSION'))"
3.9
I think the weird thing is that it's trying to run the wrong python3: /nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6/bin/python3
whereas what's installed is
[nix-shell:~/dev/research/julia/permuted_sgd]$ which python3
/nix/store/rppr9s436950i1dlzknbmz40m2xqqnxc-python3-3.9.9/bin/python3
FWIW part of the magic of nix-shell is that I'm freed from having a global python install across the whole system. That may be part of what's tripping it up.
PyCall just searches the $PATH
environment variable for python3
. If nix-shell uses some other mechanism for which
, that won't work.
The workaround is simply to set
ENV["PYTHON"]="/nix/store/rppr9s436950i1dlzknbmz40m2xqqnxc-python3-3.9.9/bin/python3"
Pkg.build("PyCall")
to specify the particular path that you want. (You only need to do this once and PyCall will remember the path subsequently.)
Here's my $PATH
:
[nix-shell:~/dev/research/julia/permuted_sgd]$ echo $PATH
/nix/store/79zvzq15mga6bgk5phnmw0fd2pnpim9v-bash-interactive-5.1-p8/bin:/nix/store/f1n2zyq47sjn0qfhxvrdawyzlgk4sgax-patchelf-0.13/bin:/nix/store/7wn7xx8faqirzkvh5iwj26b024jzg09p-gcc-wrapper-10.3.0/bin:/nix/store/v819nrv8d33ns36gm4v9vqydq1v95axi-gcc-10.3.0/bin:/nix/store/dhj23pp1sld19shjslkzw3y9pr3qpi61-glibc-2.33-59-bin/bin:/nix/store/abc8hz0v47jzsf048j1qx7m94bxfhpl7-coreutils-9.0/bin:/nix/store/gxd0gvw88wyl9bqjc03ypm5zs7qbaf74-binutils-wrapper-2.35.2/bin:/nix/store/8d30avp4xj1w8krq7zax1mlxgs28663y-binutils-2.35.2/bin:/nix/store/qmlbjq46nhn1v08nnb23y2myrvra8hm7-julia-bin-1.7.1/bin:/nix/store/rppr9s436950i1dlzknbmz40m2xqqnxc-python3-3.9.9/bin:/nix/store/abc8hz0v47jzsf048j1qx7m94bxfhpl7-coreutils-9.0/bin:/nix/store/r87rxnys39173q5nrlqq46vpa2203rmk-findutils-4.8.0/bin:/nix/store/xgqrjhz9sx8bllvayz18sql2dfd89q4g-diffutils-3.8/bin:/nix/store/aw3vgxn4fdrjqgmc94fr582hjhr2z3p3-gnused-4.8/bin:/nix/store/rvdb7057bmg3rasbqq8lzl10dffy3p31-gnugrep-3.7/bin:/nix/store/3qmgmnz3msrk0cf0qgcyja0wzyfhpxc2-gawk-5.1.1/bin:/nix/store/xc1dbg8mc8hd6bq7zizxf5nyrljk8az0-gnutar-1.34/bin:/nix/store/1wads5y31dky89hxnn5zmiri3c72kdpc-gzip-1.11/bin:/nix/store/l8d7zz3ninmgg71738q485anfjh5yd6q-bzip2-1.0.6.0.2-bin/bin:/nix/store/ba439awj33pw4l4bj95k4dy58nx69b8v-gnumake-4.3/bin:/nix/store/iqprjr5k5385bhf1dzj07zwd5p43py1n-bash-5.1-p12/bin:/nix/store/22avws4xw0chqniqym3q0w4nhdcr0hh2-patch-2.7.6/bin:/nix/store/aq0v28n1ka8m1ayg6wrpbjy00bb7fj3k-xz-5.2.5-bin/bin:/run/wrappers/bin:/home/skainswo/.nix-profile/bin:/etc/profiles/per-user/skainswo/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin
which includes /nix/store/rppr9s436950i1dlzknbmz40m2xqqnxc-python3-3.9.9/bin
and no other python installations.
(You only need to do this once and PyCall will remember the path subsequently.)
How does PyCall remember this path? Is it remembered per Julia session or forever or something else?
Perhaps it's remembering an incorrect path?
I did a little more poking around and I think I better understand the issue now. The problem is that part of PyCall's ] build
process involves the generation of a file ~/.julia/packages/PyCall/L0fLP/deps/deps.jl
:
[nix-shell:~/dev/research/julia/pumpkin]$ cat /home/skainswo/.julia/packages/PyCall/BD546/deps/deps.jl
const python = "/nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6/bin/python3"
const libpython = "/nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6/lib/libpython3.9.so.1.0"
const pyprogramname = "/nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6/bin/python3"
const pyversion_build = v"3.9.6"
const PYTHONHOME = "/nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6:/nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6"
"True if we are using the Python distribution in the Conda package."
const conda = false
Because this file lives "forever" in ~/.julia
, it becomes outdated after changing the python version (upgrading, etc). Setting the PYTHON
env var works as a workaround. Still I think it'd be nice if it just pulled the python path out of PATH
instead of generating this deps.jl
cruft. What is the purpose in creating deps.jl
as part of the build process?
I just recently wanted to make a Julia project using a Nix shell and ran into this problem. I was able to solve it by just hacking the PYTHONPATH
and everything just seemd to work. This is my shell for reference.
{ lib, writeText, writeShellApplication, substituteAll, gum, inputs, pkgs
, hosts ? { }, ... }:
let
inherit (lib) mapAttrsToList concatStringsSep;
inherit (lib.campground) override-meta;
src = ./.;
julia-env = pkgs.julia.withPackages.override { extraLibs = [ python-env ]; } [
"IJulia"
"CSV"
"DataFrames"
"PythonCall"
];
pypkgs-build-requirements = { redfin = [ "setuptools" ]; };
p2n-overrides = pkgs.poetry2nix.defaultPoetryOverrides.extend (self: super:
builtins.mapAttrs (package: build-requirements:
(builtins.getAttr package super).overridePythonAttrs (old: {
buildInputs = (old.buildInputs or [ ]) ++ (builtins.map (pkg:
if builtins.isString pkg then builtins.getAttr pkg super else pkg)
build-requirements);
})) pypkgs-build-requirements);
python-env = pkgs.poetry2nix.mkPoetryEnv {
projectDir = ./.;
overrides = p2n-overrides;
python = pkgs.python311;
};
in pkgs.mkShell {
buildInputs = [
pkgs.poetry
julia-env
python-env
];
env = {
PYTHONPATH = "${python-env}/lib/python3.11/site-packages:${python-env}/lib/site-packages:$PYTHONPATH";
};
shellHook = ''
echo "Poetry environment and Julia project set up."
'';
}
I'm running into some unexpected hiccups building PyCall.jl on NixOS. I have successfully used PyCall.jl on NixOS in the past, so I'm a bit stumped as to why it's borked now. I get the following failure:
It appears to be hung up on some aspect of the conda installation. However, building Conda.jl works without any issues:
A few things are weird to me about this situation:
cannot execute /home/skainswo/.julia/conda/3/conda.exe: NIX_LD or NIX_LD_x86_64-linux is not set
suggests to me that Conda.jl is smart enough to use nix-ld when it's available, but I haven't been able to find anything about this in the docs or in the sources for Conda.jl or PyCall.jl. Where is this warning coming from?/nix/store/nki9ywqzbvz68vr75kn2r7g1q84f5agy-python3-3.9.6/bin/python3 -c \"import distutils.sysconfig; print(distutils.sysconfig.get_config_var('VERSION'))\"
, but this is very odd since I don't even have that version of python installed! I have python 3.9.9 with a different hash entirely! How is it hallucinating this python install that does not exist?The main thing that has changed since the last time this worked for me is that I upgraded NixOS from 21.05 to 21.11.
Here's my shell.nix for reference:
and here's the version of python that's actually available: