1

I use pyvenv to create new environments and activate them. I, sometimes, use libs that are not in standard lib, and I usually have to install them with pip3 module/command.

For example, to install folium, I have to M-! pip3 install folium within activated environment.

Is there a way to automatically check, and if necessary, install all needed libs (in a single file/buffer) at file evaluation time?

2
  • One way is to write a function that takes a list of library names and installs them (if they are not installed already), then add the function to your init file. You can then use file-local variables or directory-local variables to define that list of library names for a specific file or a specific directory and evaluate the function you wrote with the list of library names as argument. Commented Aug 1 at 15:39
  • Do you have a requirements.txt for your project? pip should be able to use that to install the correct dependencies. This is more a question of python tooling, than emacs. Commented Aug 8 at 7:43

1 Answer 1

1

[Expanding my comment into an answer.]

One way is to write a function that takes a list of library names and installs them (if they are not installed already), then add the function to your init file. You can then use file-local variables or directory-local variables to define that list of library names for a specific file or a specific directory and evaluate the function you wrote with the list of library names as argument.

Here's a function, pip-package-install-list,that takes a list of library names and installs each one (if it is not installed already):

(defun pip-package-installedp (pkg) (message pkg) (= 0 (call-process "pip" nil nil nil "show" pkg))) (defun pip-package-install (pkg) (shell-command (format "pip install %s" pkg) nil nil)) (defun pip-package-install-list (l) "Install packages in the list L if not installed already." (dolist (pkg l) (unless (pip-package-installedp pkg) (message "Installing %s..." pkg) (pip-package-install pkg)))) 

It makes use of two helper functions, one to check whether the package is installed already and another to install it.

You need to put the above in your init file and restart your Emacs to ensure that the function is defined.

You can then add a local variables section to a Python file, so that when the file is opened, the local variables are evaluated as described in the links above. Here is a file that imports a couple of packages that are not normally installed (and one, xarray, that is):

#! /usr/bin/env python3 # -*- coding: utf-8 -*- """ Dummy """ # make pylint STFU about some things # pylint: disable-msg=C0103 import sys import argparse import xarray import foo12 import foo2bar def main(args): """ Main """ print(args) if args: return 0 return 1 if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("-f", "--file", dest="filename", help="write report to FILE", metavar="FILE") parser.add_argument("-q", "--quiet", action="store_false", dest="verbose", default=True, help="don't print status messages to stdout") myargs = parser.parse_args() status = main(myargs) sys.exit(status) # Local variables: # liblist: ("foo12" # "xarray" # "foo2bar") # eval: (pip-package-install-list liblist) # End: 

When you open the file, you are asked whether to allow the evaluation of the local variables and, assuming you accept, the liblist variable is set to the list you specify and the eval pseaudo variable causes the pip-packape-install-list function to be called with the liblist as argument, causing any missing packages to be installed. You can check by running the file from the command line and checking that no "missing package" errors are thrown.

Opening the *Messages* buffer and going to the end before opening the Python file will show you details of what is happening and what is being installed.

If you add another import to your python file and add that package to the liblist variable, you can re-evaluate the local variables by saying M-x normal-mode.

Using directory-local variables for a whole project is similar: see the appropriate link above.

1
  • Thank you. Great answer! Commented Aug 3 at 6:36

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.