0

I have the following Makefile on a folder on Windows 11.

VENV = test
PYTHON = $(VENV)/Scripts/python
PIP = $(VENV)/Scripts/pip
ACTIVATE = $(VENV)/Scripts/activate

run: $(ACTIVATE)
    $(PYTHON) api/app.py

$(ACTIVATE): requirements.txt
    py -m venv $(VENV)
    $(PIP) install -r requirements.txt

deactivate: $(ACTIVATE)
    $(VENV)/deactivate

.PHONY: clean
clean:
    rmdir $(VENV) /s /q
    rmdir api\__pycache__ /s /q

When I execute make run on PowerShell, it suscessfully creates the virtual environment, installs the requirements and runs app.py. However, I have noticed that it is not running in the virtual environment. In other words, it is not activating the environment before running.

The reason why I think it is not running on the virtual environment is because when I stop the app, the command line doesn't show '(test)' on the left, as it would usually do. I have also checked some installed packages to make sure I was not in the virtual environment.

If I did it by hand, I would just type test\Scripts\activate. I have tried adding this inside the run command before executing api/app.py, but it doesn't seem to be activating it either. I have also tried the solution here, i.e. adding test\Scripts\activate && exec bash right before executing the app but exec is not recognized as a command. Replacing test\Scripts\activate by $(ACTIVATE) does not work either because it says that test is not recognized as a command.

What can I do to make sure that api/app.py is running in the virtual environment?

sinoroc
  • 18,409
  • 2
  • 39
  • 70
Javi
  • 113
  • 6
  • I recommend you do not try to activate the environment, but instead call the executables placed in the virtual environment's `Scripts` directory (or `bin` on anything else but Windows). For example: `test/Scripts/python -m pip ...`. -- I do not think that *Makefile* rules such as `activate` and `deactivate` make sense. – sinoroc Apr 18 '23 at 17:26
  • @sinoroc shouldn't then `$(PYTHON) api/app.py` run it in the environment? Since `PYTHON = $(VENV)/Scripts/python` is calling an executable. – Javi Apr 18 '23 at 19:52
  • Right... indeed it should. I had not paid attention close enough. But anyway the reason you give for thinking that `$(PYTHON) api/app.py` is not running in the virtual environment does not seem correct at all to me. Indeed I do not think you should expect to see the `(test) ` prefix at the command line prompt after running `make run`, because I do not think that the virtual environment would stay activated after `make run` finishes. – sinoroc Apr 18 '23 at 20:03

1 Answers1

1

I think I would do something like this:

VENV = test
PYTHON = $(VENV)/Scripts/python

.PHONY: run
run: $(PYTHON)
    $(PYTHON) api/app.py

$(PYTHON):
    py -m venv $(VENV)
    $(PYTHON) -m pip install --requirement requirements.txt

.PHONY: clean
clean:
    rmdir $(VENV) /s /q
    rmdir api/__pycache__ /s /q

I do not think it makes sense to have activate and deactivate rules in a Makefile and I do not think it would work even, so I skip them. The trick you linked in your question is meant for bash on Linux, I am quite sure it would not work on Windows, and I can not think of a solution that would work on Windows.

sinoroc
  • 18,409
  • 2
  • 39
  • 70
  • When I run that I get a permission denied error when trying to access `test/Scripts/python.exe`. – Javi Apr 19 '23 at 19:27
  • I also wonder why you think 'activate' and 'deactivate' rules don't make sense in a *Makefile*. – Javi Apr 19 '23 at 19:28
  • I am surprised by the "*permission denied error*". I do not have Windows to test this. -- *Makefile* rules `activate` and `deactivate` do not make sense because that is not what `make` is for. Maybe there is a way to make it work (on Windows, in Powershell), but I do not know one. – sinoroc Apr 19 '23 at 19:41
  • I am surprised too, since it doesn't throw this error with my version. Thanks anyway. – Javi Apr 19 '23 at 19:44
  • When do you get the "permission denied error"? Thinking about it, it could be because `requirements.txt` has been modified after `$(PYTHON)` has been created, so `make` tries to update `$(PYTHON)` and fails. There should be a way to tell `make` to never try to recreate `$(PYTHON)` if it already exists (even if `requirements.txt` is newer). – sinoroc Apr 19 '23 at 19:46
  • Right after `py -m venv test`, so it may be what you say. – Javi Apr 19 '23 at 19:55
  • It should be easy to test. Delete the env, call `make run` a couple of times, check that it works, then modify `requirements.txt` and call `make run` again. – sinoroc Apr 19 '23 at 20:00
  • It seems to be working now. How should I confirm that it is running on the virtual environment? – Javi Apr 19 '23 at 21:03
  • 1
    I guess `api/app.py` runs in the virtual environment if `api/app.py` can import something that was installed from the `requirements.txt` file. Also in `api/app.py` you can add `import sys; print(sys.executable)` and checks that it displays the path to `test/Scripts/python.exe`. – sinoroc Apr 19 '23 at 21:05
  • Yes, it is priting the path to the env executable, thanks! – Javi Apr 19 '23 at 21:08