casey / just

🤖 Just a command runner
https://just.systems
Creative Commons Zero v1.0 Universal
21.39k stars 476 forks source link

How to invoke a virtual environment for Python on Windows with just? #730

Closed epogrebnyak closed 2 years ago

epogrebnyak commented 3 years ago

Thank you for a great tool. It is fun and makes one productive.

I noticed calling a bacthc file on Windows fails:

λ just env-start
call env1\Scripts\activate.bat
sh: call: command not found

Any ideas how to fix?

In my justfile I have:

env-start:
  call env1\Scripts\activate.bat

call env1\Scripts\activate.bat passes on command line

Many thanks!

casey commented 3 years ago

Hi Evgeny, thanks for the kind words! I'm glad you like Just.

By default, Just uses sh to execute commands, and I believe that call is only needed in batch files or when using cmd.exe.

You have a few options for calling a batch file.

If you don't change the shell that Just uses, I think you can call batch files using cmd.exe:

env-start:
  cmd.exe /C env1/Scripts/activate.bat

Alternatively, you can change your shell to cmd.exe, in which case I believe your justfile will work unmodified:

set shell := ["cmd.exe", "/c"]

env-start:
  call env1\Scripts\activate.bat

I haven't tested either of these, so hopefully they work.

epogrebnyak commented 3 years ago

Thank you for the explaination on cmd.exe, I can't wait to test on the desktop. Meanwhile, a bit more praise and the info on workflow: just really opens a path to creativity and experimentation, in good way. My usercase is python packaging on Windows and next best alternative is invoke, great to launch python pieces, but longish for subprocess launch and generally needs extra bindings for commands on Windows. With just I was able to go from 2-3 first commands to see if things work, to 7-8 commands that I often used and needed to automate, in less than 30-40 min, changing them, trying and improving. I look forward to people sharing their justfile s and workflows.

As for barriers - had to come terms that a tool is shell dependent and I really do have proper shells in via cmder or git for windows, also there is no highlighting in VS Code for justfile, maybe can be tuned.

Providing the detail as you might be interested to know your tool is really impactful.

casey commented 3 years ago

Thank you for the explaination on cmd.exe, I can't wait to test on the desktop.

Meanwhile, a bit more praise and the info on workflow: just really opens a path to creativity and experimentation, in good way. My usercase is python packaging on Windows and next best alternative is invoke, great to launch python pieces, but longish for subprocess launch and generally needs extra bindings for commands on Windows. With just I was able to go from 2-3 first commands to see if things work, to 7-8 commands that I often used and needed to automate, in less than 30-40 min, changing them, trying and improving. I look forward to people sharing their justfile s and workflows.

That's really great to hear, I definitely appreciate feedback like this!

I think it's definitely the case that being able to something simply easily, and then incrementally do more is one of Just's strengths.

In addition to the readme, another way to learn more about Just's features is to check out just's justfile, and also justfiles that other people have written on github.

I often check out the justfiles that people post to GitHub, to try to figure out which features are being used.

As for barriers - had to come terms that a tool is shell dependent and I really do have proper shells in via cmder or git for windows, also there is no highlighting in VS Code for justfile, maybe can be tuned.

cmd.exe is definitely not great, but you can use it. Another option is to try WSL.

I opened issue #732 re syntax highlighting for VS Code, in case someone wants to take a crack at that. Just's syntax is close enough to Make's that if you tell VS Code to use Make syntax highlighting, it'll probably be good enough.

epogrebnyak commented 3 years ago

Just tried:

env-start:
  cmd.exe /C env1/Scripts/activate.bat

I think shell mechanics are not in our favour here: it seems an extra shell is spawn (the prompt changes), but the environment is not entered, for some reason (eg pip freeze shows big list of packages, not a small one). On exit cammand I'm into regular shell prompt.

Maybe there are more cmd.exe flags for this type of action that I should look for.

epogrebnyak commented 3 years ago

Thanks for all the extra detail!

In addition to the readme, another way to learn more about Just's features is to check out just's justfile, and also justfiles that other people have written on github.

My little just file is there too! ;-)

epogrebnyak commented 3 years ago

In addition to the readme, another way to learn more about Just's features is to check out just's justfile, and also justfiles that other people have written on github.

Is there any clever way to sort and see just files for python projects? Or just browsing?

casey commented 3 years ago

Is there any clever way to sort and see just files for python projects? Or just browsing?

If you add python to the search, I think most of the justfiles will be for python projects:

https://github.com/search?q=filename%3Ajustfile+python&type=Code

I think shell mechanics are not in our favour here: it seems an extra shell is spawn (the prompt changes), but the environment is not entered, for some reason (eg pip freeze shows big list of packages, not a small one). On exit cammand I'm into regular shell prompt.

Ahh, I see. So with env1/Scripts/activate.bat you're trying to activate a new python environment? That's interesting, I would expect it to work. I don't know much about python virtual environments, so unfortunately I can't be much help there.

I do imagine that it might be difficult to get a mix of sh and cmd.exe to work, since virtual environment changes are communicated by environment variables, and those might get messed up.

epogrebnyak commented 3 years ago

Mind if I rename the issue and leave it open to see if someone can come up with an environment start line for Windows? Can also close as original question is fully answered.

For python packacking justfiles I looked for typical commands like black, mypy, sphinx (not just python string itself) and found a few good ideas that can integrate in workflow.

As for env-start command it can now just echo a reminder on what to type in command line, as a helper.

casey commented 3 years ago

Mind if I rename the issue and leave it open to see if someone can come up with an environment start line for Windows? Can also close as original question is fully answered.

That sounds good, feel free.

casey commented 3 years ago

@epogrebnyak There's actually a great Just plugin for VS Code that I totally forgot existed: https://github.com/skellock/vscode-just

epogrebnyak commented 3 years ago

@epogrebnyak There's actually a great Just plugin for VS Code that I totally forgot existed: https://github.com/skellock/vscode-just

Just installed it inb VS Code and now the linting is there, thank you. The plug-in is quite popular with 1K+ installs. For those interested look for justfile in VS Code extenstions (repo itself does not provide installation instructions).

0x7FFFFFFFFFFFFFFF commented 3 years ago

Does anyone find a way to make the activate script work? I tried the several methods and none of them work. Below are what I've tried.

echo call venv\Scripts\activate.bat
call venv\Scripts\activate.bat
venv\Scripts\activate.bat

Btw, I'm on Windows using Windows Terminal with cmd as just's shell.

casey commented 3 years ago

Can you get venv to generate a powershell activation script? That's my only thought, since cmd.exe/bat files can be weird on windows, maybe trying powershell would be a good idea.

Are you getting an error?

casey commented 3 years ago

Whoops, didn't mean to close.

0x7FFFFFFFFFFFFFFF commented 3 years ago

Yes, there is a PowerShell version of the activation file. But it can only be used in a PowerShell command line.

PS C:\my_projects\project1> .\venv\Scripts\Activate.ps1
(venv) PS C:\my_projects\project1>
casey commented 3 years ago

If it's convenient, you could switch your whole justfile to use powershell:

set shell := ["powershell.exe", "-c"]

env:
    .\venv\Scripts\Activate.ps1

You can also use it for a single recipe like this:

set shell := ["powershell.exe", "-c"]

env:
    #!/path/to/powershell.exe
    .\venv\Scripts\Activate.ps1

(I don't use windows, so I'm not sure what path should be used in the #!.)

0x7FFFFFFFFFFFFFFF commented 3 years ago

If it's convenient, you could switch your whole justfile to use powershell:

set shell := ["powershell.exe", "-c"]

env:
    .\venv\Scripts\Activate.ps1

You can also use it for a single recipe like this:

set shell := ["powershell.exe", "-c"]

env:
    #!/path/to/powershell.exe
    .\venv\Scripts\Activate.ps1

(I don't use windows, so I'm not sure what path should be used in the #!.)

It doesn't work by my test. The first method opens powershell in a new process and probably run the activate script there. The second method (I changed to correct powershell full path) simply opens the activate script.

casey commented 3 years ago

What about this:

set shell := ["powershell.exe", "-c"]

env:
    #!/path/to/powershell.exe
    . .\venv\Scripts\Activate.ps1

(Note the . before the activate script.) Using a . should run all the commands in the script but leave you in the same shell, so you can run commands afterwards.

0x7FFFFFFFFFFFFFFF commented 3 years ago

What about this:

set shell := ["powershell.exe", "-c"]

env:
    #!/path/to/powershell.exe
    . .\venv\Scripts\Activate.ps1

(Note the . before the activate script.) Using a . should run all the commands in the script but leave you in the same shell, so you can run commands afterwards.

This also opens the script file instead of executing it.

casey commented 3 years ago

Ahh, that's too bad.

madig commented 2 years ago

Do I understand correctly that Just's (and Make's) one-shell-launch-per-line approach means I'd have to activate the venv for every single line where I want to use it, except when I go the shebang route? Is there a way to run it at, say, the start, and source the env vars it leaves behind or launch new shells from that env? AFAIK, that's all "activation" does.

The other method is of course to run venv/bin/python directly, which should usually pick up on the venv by itself. Not sure if this works everywhere though.

casey commented 2 years ago

@madig

Do I understand correctly that Just's (and Make's) one-shell-launch-per-line approach means I'd have to activate the venv for every single line where I want to use it, except when I go the shebang route?

Yup, that's correct.

Is there a way to run it at, say, the start, and source the env vars it leaves behind or launch new shells from that env? AFAIK, that's all "activation" does.

I don't think there's a good way to do this. Can you get it to print out the variables it sets?

madig commented 2 years ago

Well, for PowerShell, it's "easy". There's a script at e.g. https://github.com/nightroman/PowerShelf/blob/master/Invoke-Environment.ps1 (used for importing Visual Studio variables from its batch script). For others, hm. Maybe Calling stuff inside the venv bin directory is easiest :)

casey commented 2 years ago

I added a note to the readme in #1229 that the best way to use python virtual environments is to execute the binaries directly, e.g. to call ./venv-name/bin/python3 instead of sourcing first and then calling python3.