m-labs / artiq

A leading-edge control system for quantum information experiments
https://m-labs.hk/artiq
GNU Lesser General Public License v3.0
425 stars 196 forks source link

`sys.path` different for `artiq_master` and `artiq_run` #1819

Open lriesebos opened 2 years ago

lriesebos commented 2 years ago

Question

Category: Environment

Description

sys.path is different when running an experiment through the ARTIQ master or using artiq_run. Most noticeable, the current working directory is added when using ARTIQ master, which is very convenient. I could not quickly find why it is different for the two cases. Is there a good reason for that? It might be more convenient to unify that a bit more, preferably to the sys.path of ARTIQ master.

For example when using print(sys.path) in an experiment:

Using the ARTIQ master ``` ['/home/leon/projects/dax-example', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python38.zip', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python3.8', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python3.8/lib-dynload', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python3.8/site-packages', '/nix/store/8c7wzlwkg247n45mmcx86g8qfl7rxi4b-python3-3.8.11-env/lib/python3.8/site-packages'] ```
Using ARTIQ run ``` ['/nix/store/qi1m1rz4kba12h0f1505bmxqxqw94mm1-python3.8-artiq-6.7648.f49f1fcb/bin', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python38.zip', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python3.8', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python3.8/lib-dynload', '/nix/store/j2hdhabhzvwy7zbw96pi7m7i066snh2i-python3-3.8.11/lib/python3.8/site-packages', '/nix/store/8c7wzlwkg247n45mmcx86g8qfl7rxi4b-python3-3.8.11-env/lib/python3.8/site-packages', '/nix/store/qi1m1rz4kba12h0f1505bmxqxqw94mm1-python3.8-artiq-6.7648.f49f1fcb/lib/python3.8/site-packages', '/nix/store/yg2jhn8k972dcx1fmxs6hj7lx2m5fjxa-python3.8-llvmlite-artiq-0.23.0.dev/lib/python3.8/site-packages', '/nix/store/rqcdjsxj5l7dwq2c64jj147bk4sc3fby-python3.8-sipyco-1.2/lib/python3.8/site-packages', '/nix/store/kadip07ykd8fi7qkw8wqfw05pnjddkrg-python3.8-numpy-1.20.2/lib/python3.8/site-packages', '/nix/store/vdxyfn2m82ynn90fm7ip8gaxfnp5b455-python3.8-pythonparser-1.4/lib/python3.8/site-packages', '/nix/store/i23rg16s6vgmw94cxgyxjdhbmmlgra2i-python3.8-regex-2021.3.17/lib/python3.8/site-packages', '/nix/store/73d2dpgc86l0pj57m04ys2nbg9mzrc9q-python3.8-pygit2-1.5.0/lib/python3.8/site-packages', '/nix/store/0z7g88hc0z0d2wjsf04x17j64m8pqw6d-python3.8-cached-property-1.5.2/lib/python3.8/site-packages', '/nix/store/bcld0xmchlm7v9sax1j0fca8f3qjf47s-python3.8-pycparser-2.20/lib/python3.8/site-packages', '/nix/store/fslmd0hrl6ngw1ayh1r8lq0r65kk7bnz-python3.8-cffi-1.14.5/lib/python3.8/site-packages', '/nix/store/6mdr3941yrdahj6yk9flb7qzw222w1fk-python3.8-python-dateutil-2.8.1/lib/python3.8/site-packages', '/nix/store/hk75cmdq9a28gqi59flwwn1gq1i09mzx-python3.8-six-1.15.0/lib/python3.8/site-packages', '/nix/store/kqhgzyj7vwb9z82jnsjcbg23r8fifnr8-python3.8-scipy-1.6.1/lib/python3.8/site-packages', '/nix/store/2cm6pm0vd2sk01g2i9lwdzxaqscqlzck-python3.8-prettytable-2.1.0/lib/python3.8/site-packages', '/nix/store/5sayjshbbpk71nzmrhsbfkvs7kn7rc6i-python3.8-wcwidth-0.2.5/lib/python3.8/site-packages', '/nix/store/dy6ra6snpg1nplg69ac3a5g2llgf740m-python3.8-setuptools-54.2.0/lib/python3.8/site-packages', '/nix/store/j4j2dn5gwk0gx5cjf9m8qcbr959ngg78-python3.8-pyserial-3.5/lib/python3.8/site-packages', '/nix/store/i6iq24bd42r0iyn43bxx2imjc6bdyqz2-python3.8-python-Levenshtein-0.12.2/lib/python3.8/site-packages', '/nix/store/b9v4mkcy4i176g4k6vxjgg1bisb8xrby-python3.8-h5py-3.2.1/lib/python3.8/site-packages', '/nix/store/ldjjjg9j1r5khikcyy66n8yxwgmshnzc-python3.8-dbus-python-1.2.16/lib/python3.8/site-packages', '/nix/store/r4g6llhbgy0k263wlz5yhw6fyiky1in1-python3.8-PyQt5_sip-12.8.1/lib/python3.8/site-packages', '/nix/store/hxxaqdffs2zzsqhlc2v20z3zhm3xsckv-python3.8-PyQt5-5.15.2/lib/python3.8/site-packages', '/nix/store/lclvy6zs6gwj2sl52r8k6n3v8asyh1ix-python3.8-pyqtgraph-0.11.1/lib/python3.8/site-packages', '/nix/store/b7gig6rprj0ba489ax6bqqcnkk0bng4l-python3.8-pyopengl-3.1.4/lib/python3.8/site-packages', '/nix/store/zbygdf7w50nhvz1w4adlcc7i2zpv2c69-python3.8-Pillow-8.3.2/lib/python3.8/site-packages', '/nix/store/czhrbrik5v9pdafalgv8yw0arvm6i5i0-python3.8-olefile-0.46/lib/python3.8/site-packages', '/nix/store/l0nnlfwvzv23z2vh0sq0b939a0iqfy5f-python3.8-defusedxml-0.7.1/lib/python3.8/site-packages', '/nix/store/19iskrrv1xqizkr9pds8pw7jmrvhjp6s-python3.8-qasync-0.10.0/lib/python3.8/site-packages'] ```
sbourdeauducq commented 2 years ago

Is there a good reason for that?

Not as far as I know. Let us know if you find out what is going on.

stevefan1999 commented 2 years ago

If you are using Nix, the installed frontends will be wrapped by Nix to rewrite the Python site-packages to Nix stores, then runs original entrypoint. It looks something like this:

#! /nix/store/l0wlqpbsvh1pgvhcdhw7qkka3d31si7k-bash-5.1-p8/bin/bash -e
export NIX_PYTHONPREFIX='/nix/store/0r3wjsc45csfbj3fc5ckpccgiqblvp7m-python3-3.9.6-env'
export NIX_PYTHONEXECUTABLE='/nix/store/0r3wjsc45csfbj3fc5ckpccgiqblvp7m-python3-3.9.6-env/bin/python3.9'
export NIX_PYTHONPATH='/nix/store/0r3wjsc45csfbj3fc5ckpccgiqblvp7m-python3-3.9.6-env/lib/python3.9/site-packages'
export PYTHONNOUSERSITE='true'
exec "/nix/store/d5bvvm42a2j2r5c47vb322cph4hq8b5w-python3.9-artiq-7.0-dev/bin/artiq_run"  "$@"

But if you ran an experiment through master, it will spawn a worker as subprocess: https://github.com/m-labs/artiq/blob/9eee0e5a7b2bfabf70307ba0e1999cd6263a8e97/artiq/master/worker.py#L89-L93

Since it is running an internal module using python -m artiq.master.worker_impl, indeed it will not include Nix wrappers to the package resolution path.

However, this also means setting PYTHONPATH as a global in the shell of master will modify the package paths of the worker (as a subprocess), because the environmental variables of the child process spawned are inherited from the parent

sbourdeauducq commented 2 years ago
  1. This doesn't explain the difference with the current working directory.

Since it is running an internal module using python -m artiq.master.worker_impl, indeed it will not include Nix wrappers to the package resolution path.

  1. This is completely wrong - the code you posted even shows it is using sys.executable and not "python"; the former points to the Nix wrappers. You could have verified it in 5 minutes with the REPL.
stevefan1999 commented 2 years ago

Hmm, right though, but the general intuition should lead to the correct way. While sys.executable is not "python" and is still wrapped by Nix:

#! /nix/store/l0wlqpbsvh1pgvhcdhw7qkka3d31si7k-bash-5.1-p8/bin/bash -e
export NIX_PYTHONPREFIX='/nix/store/cyvz1cl6g3z50gp2fk0kj6ygw8mrap7i-python3-3.9.6-env'
export NIX_PYTHONEXECUTABLE='/nix/store/cyvz1cl6g3z50gp2fk0kj6ygw8mrap7i-python3-3.9.6-env/bin/python3.9'
export NIX_PYTHONPATH='/nix/store/cyvz1cl6g3z50gp2fk0kj6ygw8mrap7i-python3-3.9.6-env/lib/python3.9/site-packages'
export PYTHONNOUSERSITE='true'
exec "/nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6/bin/python3.9"  "$@"

here I found out there are more wrappers in the installed frontends and not just the default Nix Python wrapper.

stevefan1999@old-nixbld ~/D/g/g/s/artiq (patch-master-proxy-coredev) [1]> cat /nix/store/834df4ms8irra3anbhznf7kvyw64bdiv-python3.9-artiq-7.0-dev/bin/artiq_master                                                      artiq-dev-shell 
#! /nix/store/l0wlqpbsvh1pgvhcdhw7qkka3d31si7k-bash-5.1-p8/bin/bash -e
export PATH='/nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6/bin:/nix/store/834df4ms8irra3anbhznf7kvyw64bdiv-python3.9-artiq-7.0-dev/bin:/nix/store/ax726p71h3g3ys9wq9fwmn6l0pa9aacy-llvm-11.1.0-dev/bin:/nix/store/vx4bsnnglvbhhi39w4ccfdnwz2y1vbpj-ncurses-6.2-dev/bin:/nix/store/72vdginhi637lxyii5fnpmvf4jzc4gbk-ncurses-6.2/bin:/nix/store/4x19kd5fy4ivkp3sb72nks5y6sdfni2m-llvm-11.1.0/bin:/nix/store/dy3skn94kgmximgraiknlgql8j33qx0x-lld-11.1.0/bin:/nix/store/jlvrbspsxbsdbbjyq58dp8y1h0y7ay2q-python3.9-sipyco/bin:/nix/store/h5fjizjdjvzbg3dl9dwh6r384rypl3yv-python3.9-pybase64-1.2.0/bin:/nix/store/bhs02rwyhgsdwriw9f1amkx9020zpir5-python3.9-numpy-1.21.2/bin:/nix/store/yzvfxvq0f0f0hnphpfxkw2fpvxlxpga7-qtdeclarative-5.15.3-bin/bin:/nix/store/46pq3pgwxpp2lgzmvlmpq4g25q43gl7k-python3.9-PyQt5-5.15.4/bin:/nix/store/v7sc3c9h2nqf1byjxa8ygfb7g274256b-python3.9-pyserial-3.5/bin'${PATH:+':'}$PATH
export PYTHONNOUSERSITE='true'
if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi
export FONTCONFIG_FILE='/nix/store/6m6cp1d1l8dva67v8hxbbdvz0vqbpj3s-fontconfig-2.13.94/etc/fonts/fonts.conf'
exec -a "$0" "/nix/store/834df4ms8irra3anbhznf7kvyw64bdiv-python3.9-artiq-7.0-dev/bin/.artiq_master-wrapped"  "$@"
stevefan1999@old-nixbld ~/D/g/g/s/artiq (patch-master-proxy-coredev) [SIGINT]> cat /nix/store/834df4ms8irra3anbhznf7kvyw64bdiv-python3.9-artiq-7.0-dev/bin/.artiq_master-wrapped                                        artiq-dev-shell 
#!/nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6/bin/python3.9
# -*- coding: utf-8 -*-
import sys;import site;import functools;sys.argv[0] = '/nix/store/834df4ms8irra3anbhznf7kvyw64bdiv-python3.9-artiq-7.0-dev/bin/artiq_master';functools.reduce(lambda k, p: site.addsitedir(p, k), ['/nix/store/834df4ms8irra3anbhznf7kvyw64bdiv-python3.9-artiq-7.0-dev/lib/python3.9/site-packages','/nix/store/qbi30186kngq82c8s4czhq6phhz7id0f-python3.9-llvmlite-0.37.0-artiq/lib/python3.9/site-packages','/nix/store/jlvrbspsxbsdbbjyq58dp8y1h0y7ay2q-python3.9-sipyco/lib/python3.9/site-packages','/nix/store/h5fjizjdjvzbg3dl9dwh6r384rypl3yv-python3.9-pybase64-1.2.0/lib/python3.9/site-packages','/nix/store/bhs02rwyhgsdwriw9f1amkx9020zpir5-python3.9-numpy-1.21.2/lib/python3.9/site-packages','/nix/store/07blyf8c0f9dwwdcp7s1baw4333jx9id-python3.9-pythonparser/lib/python3.9/site-packages','/nix/store/6k1iylg8ldvr9v05b469mf3rw0dxxqzd-python3.9-regex-2021.11.10/lib/python3.9/site-packages','/nix/store/rr9215lmf12vz8zzhlc9279hwhbgbwg9-python3.9-pyqtgraph-0.12.2/lib/python3.9/site-packages','/nix/store/9h3fd3pf1rw60ppxfjj0141wg6ydksfm-python3.9-dbus-python-1.2.18/lib/python3.9/site-packages','/nix/store/nz741vr4khwa9dd1550hjfqbq3ifm1j3-python3.9-PyQt5_sip-12.9.0/lib/python3.9/site-packages','/nix/store/46pq3pgwxpp2lgzmvlmpq4g25q43gl7k-python3.9-PyQt5-5.15.4/lib/python3.9/site-packages','/nix/store/5234ii7xd3yxhv1fl1j7rq0qbrw7kg6n-python3.9-scipy-1.7.1/lib/python3.9/site-packages','/nix/store/7bpsgd4q88abgw2k3p2f7n6z6v2rcwn2-python3.9-pyopengl-3.1.4/lib/python3.9/site-packages','/nix/store/5mvxd43ix2w2vqjd4n81zrw5ynx5bc89-python3.9-Pillow-8.3.2/lib/python3.9/site-packages','/nix/store/j32dv4hacf8zyy3rjhnz79jcr08jjprw-python3.9-olefile-0.46/lib/python3.9/site-packages','/nix/store/6xj8aivj9q5ssfdm626gy1pg59yw2cn6-python3.9-defusedxml-0.7.1/lib/python3.9/site-packages','/nix/store/159rq48q1ic9p4xzwgfgw0rs0pgsvc6y-python3.9-pygit2-1.7.0/lib/python3.9/site-packages','/nix/store/sqm96lkyzvd28jz4z2fnl5466gb85m66-python3.9-cached-property-1.5.2/lib/python3.9/site-packages','/nix/store/nrf62pcs9fgjkhx1kxqiavgrdqsm8qsn-python3.9-pycparser-2.20/lib/python3.9/site-packages','/nix/store/c8lq7y7fiknvsp5xiqmyizjyk9y5xgkd-python3.9-cffi-1.14.6/lib/python3.9/site-packages','/nix/store/4szmsas2djzc6iqsqxffrxxcrbbgs6n3-python3.9-python-dateutil-2.8.2/lib/python3.9/site-packages','/nix/store/j3s61z5mdrhizcwcb41g38i3yga4kq5p-python3.9-six-1.16.0/lib/python3.9/site-packages','/nix/store/7hkdallc1gsbvl9va8inv7rz3vql01kj-python3.9-prettytable-2.2.1/lib/python3.9/site-packages','/nix/store/6n8f61w67x2hs8vizspmfals44cj6zgv-python3.9-wcwidth-0.2.5/lib/python3.9/site-packages','/nix/store/v0sq1qcn6sywrxn7cw7nbpy426g7kzgi-python3.9-setuptools-57.2.0/lib/python3.9/site-packages','/nix/store/v7sc3c9h2nqf1byjxa8ygfb7g274256b-python3.9-pyserial-3.5/lib/python3.9/site-packages','/nix/store/mk0k0qbcc2p9rxihb5sknj3kfqf9yqdw-python3.9-python-levenshtein-0.12.2/lib/python3.9/site-packages','/nix/store/n2184gb2dyn0rz65pkwpgmy4sdj7jx3j-python3.9-h5py-3.4.0/lib/python3.9/site-packages','/nix/store/q1c0adknpld3n27i2aw47f4s5205pb0j-python3.9-qasync-0.10.0/lib/python3.9/site-packages'], site._init_pathinfo());
import re
import sys
from artiq.frontend.artiq_master import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

Which corresponds to wrapPython in nixpkg. Seems like the additional site.addsitedir are what made the difference.