Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep environment variables for remote Python interpreter with PyCharm

I am using a remote Python interpreter (a virtual environment created using pew) that I access via ssh. This is working fine when manually ssh'ing to the server and using the interpreter. However when using PyCharm to call it, it forgets about the environment variables that I export in my .bashrc.

It seems when calling the Python Interpreter via ssh, PyCharm (even though started from bash) ignores the .bashrc. Here it is indicated that a shell wrapper is the solution.

#!/bin/bash -l
/path/to/interpreter/bin/python

But simply giving PyCharm this shell file as an Interpreter doesn't work (package management is disabled and when running py-code a Python terminal opens...).

How do I get a "shell wrapper" that makes sure .bashrc is executed before the PyCharm remote Python-interpreter is run?


I made sure that PyCharm runs with the correct environment. All local interpreters don't show that problem (testing in PyCharm terminal and with a Python script:)

import os
print(os.environ)

I am also aware of the "Edit Configuration" option for running specific files and the possibility to set environment variables there, however it is tedious to that for each project/file and not what I'm looking for.

like image 738
Honeybear Avatar asked Oct 11 '17 11:10

Honeybear


2 Answers

You want your wrapper to contain the "$@" when calling python in your wrapper:

#!/bin/bash -l
/path/to/interpreter/bin/python "$@"

With that trick I somehow managed to setup pycharm on Windows while using virtualenv in WSL (Ubuntu bash) and retrieving my WSL env variables.

like image 156
WenWolf Avatar answered Oct 09 '22 08:10

WenWolf


I have also been using the solution from the link you provided in the question, but with two modifications:

1. .profile instead of .bashrc

My .bashrc contains commands that make working in an interactive shell easier (setting aliases, activating a virtual environment). In .profile, I have commands that both interactive and non-interactive shells need, for example setting paths to important libraries.

I source .profile instead of .bashrc for the remote Python interpreter to avoid cluttering the environment unnecessarily and to ensure the same setup as calling python in a non-interactive (login) shell.

Furthermore, the shell wrapper that you specify as a remote interpreter must be silent. If you source .bashrc and it contains a command that prints a message like "Activated my_conda_env", this will mess with PyCharm's remote debugger.

2. Replacing python3.x with the shell wrapper

PyCharm's remote interpreter and remote debugger don't require the shell wrapper to have a specific name. However, I have observed that other functionality, like PyCharm's package tools (pip etc.), expect the interpreter to have a standard name (python, python3 or python3.6). Thus, I needed to replace the python3.6 command with the shell wrapper itself.

This has the benefit that logging in to the remote server and calling python there will also execute the wrapper. Thus, the behavior is the same as calling it through PyCharm on a local machine.

Solution

The final solution looks like this:

  1. In the bin directory of the virtual environment / conda environment:

    $ mv python3.6 python3.6_original
    $ touch python3.6
    $ chmod +x python3.6
    
  2. In python3.6:

     #!/bin/bash
    
     # Make sure that the profile was sourced, so that executing python
     # via ssh does the same as executing python locally.
     if ! (( $PROFILE_SOURCED )); then
             . ~/.profile
     fi
    
     # Get the directory of this script, see 
     # https://stackoverflow.com/a/53122736/2305095
     __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    
     # Execute the original python.
     ${__dir}/python3.6_original "$@"
    
  3. At the end of .profile:

    export PROFILE_SOURCED=1
    

python and python3 are symlinks to python3.6 by default, so they automatically point to the shell wrapper.

If you are using conda, you should also check in python3.6 whether .bashrc was already sourced. conda updates the PATH in .bashrc (and advises you to keep it there). For the remote Python interpreter, you might want to also update the PATH in the same way in python3.6 and include the paths to relevant bin directories (for example the global condabin and the respective environment's bin directory).

I have been using this solution for 6 months now and have been happy with it so far. Let me know if you encounter any problems!

like image 22
Kilian Batzner Avatar answered Oct 09 '22 09:10

Kilian Batzner