2

I'm trying to create a virtual environment, start it, and then have every command after that be executed in the virtual environment.

    1. os.system("curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py")
    2. os.system("python3 get-pip.py")
    3. os.system("mkdir Apps")
    4. os.system("pip3 install virtualenv")
    5. os.system("virtualenv virt")
    6. os.system("source virt/bin/activate")
    7. os.system("pip3 install flask")

This is the code I have right now and I am trying to create the virtual environment on line (5) and then trying to activate it on line (6) and then do the 7th line (install flask) on the virtual environment.

I also have tried os.system('. virt/bin/activate') but every-time I run the python file it goes through and it does everything except start the virtual environment.

I am running this on the terminal on Mac.

Miro J.
  • 4,270
  • 4
  • 28
  • 49
Nathan Belete
  • 111
  • 4
  • 11
  • 1
    python3 comes with `pip` and `venv`... You can `import` them rather than using `os.system` – OneCricketeer Feb 04 '20 at 23:06
  • 1
    I'd suggest using `Pipenv`, or just Docker if you are trying to make this as portable code – OneCricketeer Feb 04 '20 at 23:07
  • 1
    This is the kind of thing a shell script is very good at setting up for you. – chepner Feb 04 '20 at 23:30
  • 1
    In addition: [Things to consider when you are using `pip` inside a python script](https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program). – colidyre Feb 04 '20 at 23:49
  • 1
    Each `os.system()` call creates a separate shell instance whose context (such as, the effects of any `source` command) will be lost when that instance exits and `os.system()` returns control to your Python script. – tripleee Feb 05 '20 at 09:12
  • https://stackoverflow.com/search?q=%5Bvirtualenv%5D+activate+subprocess – phd Feb 05 '20 at 13:09

1 Answers1

3

Most likely the virtual environment is only active for the duration of the os.system() call. In many cases there is no need to activate the virtual environment, just find its bin directory and run the binaries found in it.

Something of the sort:

  • os.system('/path/to/venv/bin/python -m pip install flask')
  • os.system('/path/to/venv/bin/pip install flask')

For a different approach:

#!/usr/bin/env python3

import pathlib
import subprocess
import venv

class _EnvBuilder(venv.EnvBuilder):

    def __init__(self, *args, **kwargs):
        self.context = None
        super().__init__(*args, **kwargs)

    def post_setup(self, context):
        self.context = context

def _venv_create(venv_path):
    venv_builder = _EnvBuilder(with_pip=True)
    venv_builder.create(venv_path)
    return venv_builder.context

def _run_python_in_venv(venv_context, command):
    command = [venv_context.env_exe] + command
    print(command)
    return subprocess.check_call(command)

def _run_bin_in_venv(venv_context, command):
    command[0] = str(pathlib.Path(venv_context.bin_path).joinpath(command[0]))
    print(command)
    return subprocess.check_call(command)

def _main():
    venv_path = pathlib.Path.cwd().joinpath('virt')
    venv_context = _venv_create(venv_path)
    _run_python_in_venv(venv_context, ['-m', 'pip', 'install', '-U', 'pip'])
    _run_bin_in_venv(venv_context, ['pip', 'install', 'attrs'])

if __name__ == '__main__':
    _main()
sinoroc
  • 18,409
  • 2
  • 39
  • 70
  • @NathanBelete Does that answer your question? – sinoroc Feb 10 '20 at 22:34
  • I wanted to run a python script on a specific virtual environment, and this answer helps such that I ran "path-to-venv_python/python main.py" on a terminal. – Dane Lee May 16 '21 at 22:28