I've been testing various ways to use conda/VS Code lately - before I just decided to add the conda path to my user Path variable. I don't recall the details, but at some point user profile "profile.ps1" scripts were added, possibly autogenerated by VS Code.
The scripts are located in user/Document/PowerShell and user/Documents/WindowsPowerShell and both contain the code
#region conda initialize
# !! Contents within this block are managed by 'conda init' !!
(& "C:\Users\me\anaconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression
#endregion
The filenames of the scripts are saved in powershell $Profile variables.
Can anyone illuminate the origin of these scripts ? The are not from the conda installation...
Related
I'm trying to set up conda for PowerShell but keep running into a strange error. I'm using miniconda3 (installed for all users) and PS version 7.3.1.
The conda executable is added to $Env:PATH and I'm able to run conda init powershell, which creates a profile.ps1 file in my PowerShell directory with the following contents:
#region conda initialize
Contents within this block are managed by 'conda init' !!
If (Test-Path "C:\ProgramData\miniconda3\Scripts\conda.exe") {
(& "C:\ProgramData\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | ?{$_} | Invoke-Expression
}
#endregion
However, when restarting the terminal, I get this error:
$Env:CONDA_EXE: The term '$Env:CONDA_EXE' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
InvalidOperation: The expression after '&' in a pipeline element produced an object that was not valid. It must result in a command name,
a script block, or a CommandInfo object.
Invoke-Expression: Cannot bind argument to parameter 'Command' because it is null.
Notice the strange character in the beginning. I've seen a few discussions that have led me to believe that this might have something to do with the encoding of the profile.ps1 file or perhaps even the encoding of the output of conda.exe (if that makes any sense). I've tried changing the encoding of the profile file to UTF-8 (without BOM) and ANSI, as suggested in other threads (here and here), but this has not solved the problem.
Another thing that might be relevant to this is that when I run conda init powershell, the profile.ps1 file is actually created in a directory that's not the same as my "actual" user directory. This is because my Windows user name contains an accented character, so instead of C:\Users\AndrásAponyi\Documents\WindowsPowerShell\profile.ps1, the file gets written to C:\Users\Andr�sAponyi\Documents\WindowsPowerShell\profile.ps1 and I have to manually copy it to the correct location.
The same conda installation works perfectly fine with PowerShell version 5.1.
It seems that the issue is with the output of conda.exe that contains an unexpected character. This is causing the PowerShell profile to fail. There are a few things that you can try to resolve this issue:
Remove the existing profile.ps1 file
Create a new user profile without accented characters in the name or
rename the existing user profile to remove the accented characters
Re-run conda init powershell
Start a new PowerShell session and check if the issue has been
resolved
If the problem persists, you can try uninstalling and reinstalling Miniconda.
tl;dr
I want to find a Powershell version of the bash edit-and-execute-command widget or the zsh edit-command-line widget.
Background
Short commands get executed directly on the command-line, long complicated commands get executed from scripts. However, before they become "long", it helps to be able to test medium length commands on the command-line. To assist in this effort, editing the command in an external editor becomes very helpful. AFAIK Powershell does not support this natively as e.g. bash and zsh do.
My current attempt
I am new to Powershell, so I'm bound to make many mistakes, but I have come up with a working solution using the features of the [Microsoft.Powershell.PSConsoleReadLine] class. I am able to copy the current command-line to a file, edit the file, and then re-inject the edited version back into the command-line:
Set-PSReadLineKeyHandler -Chord "Alt+e" -ScriptBlock {
$CurrentInput = $null
# Copy current command-line input, save it to a file and clear it
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $CurrentInput, [ref] $null)
Set-Content -Path "C:\Temp\ps_${PID}.txt" -Value "$CurrentInput"
[Microsoft.PowerShell.PSConsoleReadLine]::KillRegion()
# Edit the command with gvim
Start-Job -Name EditCMD -ScriptBlock { gvim "C:\Temp\ps_${Using:PID}.txt" }
Wait-Job -Name EditCMD
# Get command back from file the temporary file and insert it into the command-line
$NewInput = (Get-Content -Path "C:\Temp\ps_${PID}.txt") -join "`n"
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($NewInput)
}
Questions
My current solution feels clunky and a somewhat fragile.
Are there other solutions? Can the current solution be improved?
Environment
OS Windows 10.0.19043.0
Powershell version 5.1.19041.1320
PSReadLine version 2.0.0
The solution I went with
Create a "baked" executable similar to what mklement0 showed. I prefer vim for this instead of `gvim, as it runs directly in the console:
'#vim -f %*' > psvim.cmd
$env:EDITOR = "psvim"
Set-PSReadLineKeyHandler -Chord "Alt+e" -Function ViEditVisually
tl;dr
PSReadLine comes with the feature you're looking for, namely the ViEditVisually function, and on Unix-like platforms it even has a default key binding.
For the feature to work, you need to set $env:VISUAL or $env:EDITOR to the name / path of your editor executable.
As of PSReadLine v2.1, if you also need to include options for your editor - such as -f for gvim - you need to create a helper executable that has the options "baked in".
Since creating a helper executable is cumbersome, a custom emulation of the feature, as you have attempted and as refined in zett42's helpful answer, may be the simpler solution for now. zett42's answer additionally links to a Gist that improves the original functionality by preserving cursor positions.
GitHub issue #3214 suggests adding support for recognizing executables plus their options in these environment variables.
Details below.
The PSReadLine module ships with such a feature, namely the ViEditVisually function.
Its default key bindings, if any, depend on PSReadLine's edit mode, which you can set with Set-PSReadLineOption -EditMode <mode>:
Windows mode (default on Windows): not bound
Emacs mode (default on macOS and Linux): Ctrl-xCtrl-e
Vi mode: v in command mode (press Esc to enter it)
Use Set-PSReadLineKeyHandler to establish a custom key binding, analogous to the approach in the question; e.g., to bind Alt-e:
Set-PSReadLineKeyHandler -Chord Alt+e -Function ViEditVisually
For the function to work, you must define the editor executable to use, via either of the following environment variables, in order of precedence: $env:VISUAL or $env:EDITOR; if no (valid) editor is defined, a warning beep is emitted and no action is taken when the function is invoked.
E.g., to use the nano editor on macOS: $env:VISUAL = 'nano'
The value must refer to an executable file - either by full path or, more typically, by name only, in which case it must be located in a directory listed in $env:PATH
Note: .ps1 scripts do not qualify as executable files, but batch files on Windows and shebang-line-based shell scripts on Unix-like platforms do.
As of PSReadLine 2.1, including options for the executable - such as --newindow --wait for code (Visual Studio Code) is not supported.
Therefore, for now, if your editor of choice requires options, you need to create a helper executable that has these options "baked in"; see examples below.
GitHub issue #3214 proposed adding support for allowing to specify the editor executable plus options as the environment-variable value, which is something that Git (which recognizes the same variables) already supports; for instance, you could then define:
$env:VISUAL = 'code --new-window --wait'
Example configuration with a helper executable for code (Visual Studio Code):
Create a helper executable in the user's home directory in this example:
On Windows:
'#code --new-window --wait %*' > "$HOME\codewait.cmd"
On Unix-like platforms:
"#!/bin/sh`ncode --new-window --wait `"$#`"" > "$HOME/codewait"; chmod a+x "$HOME/codewait"
Add a definition of $env:VISUAL pointing to the helper executable to your $PROFILE file, along with defining a custom key binding, if desired:
$env:VISUAL = "$HOME/codewait"
# Custom key binding
Set-PSReadLineKeyHandler -Chord Alt+e -Function ViEditVisually
This code has some issues:
Temp path is hardcoded, it should use $env:temp or better yet [IO.Path]::GetTempPath() (for cross-platform compatibility).
After editing the line, it doesn't replace the whole line, only the text to the left of the cursor. As noted by mklement0, we can simply replace the existing buffer instead of erasing it, which fixes the problem.
When using the right parameters for the editor, it is not required to create a job to wait for it. For VSCode this is --wait (-w) and for gvim this is --nofork (-f), which prevents these processes to detach from the console process so the PowerShell code waits until the user has closed the editor.
The temporary file is not deleted after closing the editor.
Here is my attempt at fixing the code. I don't use gvim, so I tested it with VSCode code.exe. The code below contains a commented line for gvim too (confirmed working by the OP).
Set-PSReadLineKeyHandler -Chord "Alt+e" -ScriptBlock {
$CurrentInput = $null
# Copy current console line
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $CurrentInput, [ref] $null)
# Save current console line to temp file
$tempFilePath = Join-Path ([IO.Path]::GetTempPath()) "ps_$PID.ps1"
Set-Content $tempFilePath -Value $CurrentInput -Encoding utf8
# Edit the console line using VSCode
code --new-window --wait $tempFilePath
# Uncomment for using gvim editor instead
# gvim -f $tempFilePath
# The console doesn't like the CR character, so rejoin lines using LF only.
$editedInput = ((Get-Content -LiteralPath $tempFilePath) -join "`n").Trim()
# Replace current console line with the content of the temp file
[Microsoft.PowerShell.PSConsoleReadLine]::Replace(0, $currentInput.Length, $editedInput)
Remove-Item $tempFilePath
}
Update:
This GitHub Gist includes an updated version of the code. New features including saving/restoring the cursor position, passing the cursor position to VSCode and showing a message while the console is blocked.
Notes:
A default installation of VSCode adds the directory of the VSCode binaries to $env:PATH, which enables us to write just code to launch the editor.
While UTF-8 is the default encoding for cmdlets like Set-Content on PowerShell Core, for Windows PowerShell the parameter -Encoding utf8 is required to correctly save commands that contain Unicode characters. For Get-Content specifying the encoding isn't necessary, because Windows PowerShell adds a BOM which Get-Content detects and PowerShell Core defaults to UTF-8 again.
To have Alt+E always available when you open a console, just add this code to your $profile file. Makes quick testing and editing of small code samples a breeze.
VSCode settings - for most streamlined experience, enable "Auto Save: onWindowChange". Allows you to close the editor and save the file (update the console line) with a single press to Ctrl+W.
I use Anaconda environments to manage my Python installations.
I have my Python projects organized in folders; every folder contains the code for one project and a file environments.yml that specifies the packages that a conda environment should have to run that specific Python project.
Often I start working on a project as follows:
I navigate to the project folder (in Total Commander, but that's irrelevant I think).
I look at the contents of the environment.yml file to see what conda environment needs to be used for this project
I start a Powershell session in the folder and activate the conda environment in Powershell with conda activate some_env_name.
I start the rest my programs, e.g. jupyter lab or spyder.
I feel the steps 2 and 3 should somehow be automatic, but how would I go about doing that?
After trying out various methods I settled on a function in my profile.ps1 file that gets triggered every time I start a new powershell session.
The function reads the environment name from the environment.yml file and tries to activate that environment:
function conda_here {
$first_line = Get-Content -Head 1 environment.yml # This returns "name: conda_env_name"
$env_name = $first_line.Split(": ")[-1] # This splits it into an array of [name, : , conda_env_name] and takes the last element
try {
conda activate $env_name
} catch {
Write-Host "Tried to activate environment $env_name, but failed." -ForeGroundColor Red
}
}
To let that function trigger on every powershell start I added the following after the function definition:
# Activate a conda environment when started in a dir with a .conda-env file
if ( Test-Path environment.yml ){
conda_here
}
Now whenever I start a powershell session in a folder with an environment.yml file the corresponding conda environment gets activated automatically.
Conda 4.6.14 over-writes my default PowerShell prompt from:
C:\whatevs\okay>
to:
(env) PS>
but I ideally want what it was previously:
(env) C:\whatevs\okay>
How can I undo this change to my PowerShell prompt? I like knowing what path and Conda environment I'm using whenever I execute a command! Is there a setting I can change?
I know it's possible to modify the PowerShell prompt by editing $profile. However, I want to keep the (env). Is there some quick way to get the current Conda environment so I can include it into a custom path?
Details
The file being modified by conda init is $HOME\Documents\WindowsPowerShell\profile.ps1 who's contents are:
#region conda initialize
# !! Contents within this block are managed by 'conda init' !!
(& "C:\Users\user\Anaconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression
#endregion
This is an issue with Conda 4.6.14 and can be resolved by downgrading back to 4.6.12 or upgrade to the (currently) experimental 4.7.
In virtualenvwrapper, is there a simple way to list all virtualenv on my machine?
(like what yolk -l does to list all python packages in the current virtual environment?)
CLARIFICATION: "ls -la" in my env directory does not count. I am looking for a virtualenv or virtualenvwrapper specific command.
You can use the lsvirtualenv, in which you have two options "long" or "brief":
"long" option is the default one, it searches for any hook you may have around this command and executes it, which takes more time.
"brief" just take the virtualenvs names and prints it.
brief usage:
$ lsvirtualenv -b
long usage:
$ lsvirtualenv -l
if you don't have any hooks, or don't even know what i'm talking about, just use "brief".
To list all the virtual environments (if using the anaconda distribution):
conda info --envs
Hope my answer helps someone...
Silly question. Found that there's a
lsvirtualenv
command which lists all existing virtualenv.
See the command documentation.
If you are using virtualenv or Python 3's built in venv the above answers might not work.
If you are on Linux, just locate the activate script that is always present inside a env.
locate -b '\activate' | grep "/home"
This will grab all Python virtual environments present inside your home directory.
For Mac Users, find works pretty good too
find $HOME -name "*activate" -type f
See Demo Here
Run workon with no argument to list available environments.
For conda created env use:
conda info --envs # or
conda info -e # or
conda env list
For virtualenvwrapper created env use:
lsvirtualenv
If you came here from Google, trying to find where your previously created virtualenv installation ended up, and why there is no command to find it, here's the low-down.
The design of virtualenv has a fundamental flaw of not being able to keep track of it's own created environments. Someone was not quite in their right mind when they created virtualenv without having a rudimentary way to keep track of already created environments, and certainly not fit for a time and age when most pip requirements require multi-giga-byte installations, which should certainly not go into some obscure .virtualenvs sub-directory of your ~/home.
IMO, the created virtualenv directory should be created in $CWD and a file called ~/.virtualenv (in home) should keep track of the name and path of that creation. Which is a darn good reason to use Conda/Miniconda3 instead, which does seem to keep good track of this.
As answered here, the only way to keep track of this, is to install yet another package called virtualenvwrapper. If you don't do that, you will have to search for the created directory by yourself. Clearly, if you don't remember the name or the location it was created with/at, you will most likely never find your virtual environment again...
One try to remedy the situation in windows, is by putting the following functions into your powershell profile:
# wrap virtualenv.exe and write last argument (presumably
# your virtualenv name) to the file: $HOME/.virtualenv.
function ven { if( $args.count -eq 0) {Get-Content ~/.virtualenv } else {virtualenv.exe "$args"; Write-Output ("{0} `t{1}" -f $args[-1],$PWD) | Out-File -Append $HOME/.virtualenv }}
# List what's in the file or the directories under ~/.virtualenvs
function lsven { try {Get-Content ~/.virtualenv } catch {Get-ChildItem ~\.virtualenvs -Directory | Select-Object -Property Name } }
WARNING: This will write to ~\.virtualenv...
If you use the recommended venvlink, then you can add the following powershell function, to list your available virtual environments.
# List what's in the directories of C:\venvs\
# - installed venvlink, with venvs in C:\venvs\
# - venvlink uses: ~/.venvlinkrc
function lsven { Get-ChildItem -Path C:\venvs\ -Name }
This can surely be improved to automatically detect the venvlink root directory.
To list all virtualenvs
conda env list
Output:
# conda environments:
#
D:\Programs\Anaconda3
D:\Programs\Anaconda3\envs\notebook
D:\Programs\Anaconda3\envs\snakes
D:\Programs\Anaconda3\envs\snowflakes
base * D:\Programs\Miniconda3
gluon D:\Programs\Miniconda3\envs\gluon
If using Anaconda conda env list
If using Python3 lsvirtualenv after you installed pip install virtualenvwrapper
Use below bash command to locate all virtual env in your system. You can modify the command according to your need to get in your desired format.
locate --regex "bin/activate"$ | sed 's/bin\/activate$//'
How do I find the Django virtual environment name if I forgot?. It is very Simple, you can find from the following location, if you forgot Django Virtual Environment name on Windows 10 Operating System.
c:\Users<name>\Envs<Virtual Environments>
The best answer I can find is we can check the installed python directory.
As for windows, the default directory for virtualenv and pipenv is.
/c/User/<username>/.virtualenv/
The directory(folder) inside the above directory shows all virtualenvs
Example -
ankit#ankit-PC MINGW64 ~/Desktop/study
$ ls /c/Users/ankit/.virtualenvs/
get_env_details* postactivate* postmkproject* postrmvirtualenv* predeactivate* premkvirtualenv* study-OwW1UW_H/
initialize* postdeactivate* postmkvirtualenv* preactivate* premkproject* prermvirtualenv*
study-OwW1UW_H/ is the only directory and virtualenv in the above example.
This works on Windows only:
If you are trying to find all envs created using virtualenv
search for "activate_this.py" or "pip-selfcheck.json"
if you're working on windows and conda, typing conda info --envs in cmd will show all the existing virtual envirentment.