I am using pyvenv with doom and am trying to have my python virtual environments automatically loaded when I enter a certain project.

I saw this relevant issue on pyvenv and have added the following code to my config.el

;; autoload python virtual environments
;; https://github.com/jorgenschaefer/pyvenv/issues/51#issuecomment-474785730
(defun pyvenv-autoload ()
  "Activates pyvenv version if .venv directory exists."
   (lambda (path)
     (let ((venv-path (f-expand ".venv" path)))
       (if (f-exists? venv-path)
             (pyvenv-workon venv-path))
(add-hook 'python-mode-hook 'pyvenv-autoload)

I expect that whenever I enter a python file inside a project with a .venv directory, it would automatically activate the appropriate virtual environment. However, running M-x shell-command RET which python returns /usr/bin/python when I would expect it to return something like /home/jacob/src/beets/.venv/bin/python

Some debugging:

python-mode-hook's value is


Which looks good to me.

However, pyvenv-workon's value is nil which could be the issue.

Activating and deactivating the virtual environment through pyvenv-activate and pyvenv-deactivate works as normal. If I use this method, which python returns the expected /home/jacob/src/beets/.venv/bin/python

  • Did you get anywhere with this? It's the first thing I'm looking for now I have to learn some python.
    – RichieHH
    Mar 21, 2021 at 21:18
  • If you use poetry, which I've been using mostly lately, poetry.el has a tracking mode that works well for automatically switching virtual environments in my experience. Aug 7, 2021 at 22:32

1 Answer 1


I've found that using 'projectile-after-switch-project-hook with the following function works well. The downside is that you do have to add conditional statements to the autoload-venv function as you add new projects and virtual environments. The upside is that you don't need to have a completely consistent approach to storing and naming virtual environments, i.e. you could have some in your home directory and others in the project itself.

(defun autoload-venv()
 ((string= (projectile-project-name) "project_one")
        (pyvenv-activate "~/.virtualenvs/proj1_venv"))
 ((string= (projectile-project-name) "project_two")
        (pyvenv-activate "~/project_two/proj2_venv"))))

(add-hook 'projectile-after-switch-project-hook #'autoload-venv)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.