4

I am starting a Python virtualenv through init.el (or so I would like):

(require 'virtualenvwrapper)
(venv-workon "my-python-project")

However, flycheck does not find flake8 or pylint, which are installed there. Starting emacs in a terminal with the virtualenv loaded works fine.

Is it possible to configure init.el to start a virtualenv for flycheck to use?

EDIT

Seems that this is related to an open bug in python-mode.el

2
  • Have you tried using elpy? It includes pyvenv which is able to switch virtualenvs automatically.
    – elarson
    Commented Dec 17, 2014 at 2:46
  • I don't think that the bug report is related. You neither mention virtualenv.el nor python-mode in your question.
    – user227
    Commented Dec 17, 2014 at 14:38

2 Answers 2

5

I don't think there's a prebuilt way to do this. I hacked around it like so. This depends on having all of your virtualenvs in ~/.virtualenvs, and having projectile installed.

(defvar my:virtualenv-directory "~/.virtualenvs/"
  "The directory of virtualenvs.")

(defun my:configure-python-venv ()
  "Set `python-shell-virtualenv-path' to the virtualenv directory."
  (interactive)
  (require 'projectile)
  (let* ((project-name (projectile-project-name))
         (virtualenv-path
          (file-truename
           (concat my:virtualenv-directory project-name))))
    (when (file-directory-p virtualenv-path)
      (setq python-shell-virtualenv-path virtualenv-path))))

(defun my:flycheck-python-set-executables ()
  "Set flycheck python executables for the current virtualenv."
  (let ((exec-path (python-shell-calculate-exec-path)))
    (setq-local flycheck-python-pylint-executable (executable-find "pylint"))
    (setq-local flycheck-python-flake8-executable (executable-find "flake8"))))

(defun my:flycheck-python-setup ()
  "Setup flycheck for Python with virtualenvs. "
  ;; my:flycheck-python-set-executables uses buffer-local variables
  (add-hook 'hack-local-variables-hook #'my:flycheck-python-set-executables
            nil 'local))

(add-hook 'python-mode-hook #'my:configure-python-venv)
(add-hook 'python-mode-hook #'my:flycheck-python-setup)
1
  • I changed your answer to explicitly set the local values of Flycheck variables for forward compatibility.
    – user227
    Commented Dec 17, 2014 at 14:39
0

For some unknown reason, today this works (without projectile or elpy):

;;;; Syntax checking (Flycheck)
(add-hook 'after-init-hook #'global-flycheck-mode)
(setq flycheck-check-syntax-automatically '(mode-enabled save new-line idle-change))

;; Default virtualenv (notice I didn't require virtualenvwrapper
;; python-environment or pyvenv prior to loading it. I have
;; all of them installed.)
(if (equal (getenv "VIRTUAL_ENV") nil)
    (venv-workon "my-python-project"))

;; Python autocompletion and doc browsing (Jedi, requires jedi and ipc
;; installed in the Python environment emacs is working in)
(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:setup-keys t)                      ; optional
(setq jedi:complete-on-dot t)                 ; optional

I included the flycheck (first) and jedi (last) blocks because that is the closest thing to requiring anything remotely related to Python before I set the default virtual environment. I tested it starting emacs from a shell running no virtualenv (works); running the default virtualenv (works); and running a virtualenv without jedi installed (does not work). So I'm confident this is actually working as expected.

1
  • You can use unless to simplify your if expression, and you can remove the assignment to flycheck-check-syntax-automatically, since that's the default value anyway.
    – user227
    Commented Dec 24, 2014 at 11:53

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.