0

I am trying to get the string value of a variable defined in a Python file and assign it to an elisp variable. The value is held in the variable org_file in a file config.py in the same directory as my elisp file. In the elisp file I have the following variable declaration (corgi is the name of the Python package):

(defvar corgi-org-file-path
    (shell-command-to-string "python -c \"from config import org_file; print org_file\"")
    "Path to org file retrieved from python config file")

Now if I evaluate the shell-command-to-string call alone, it returns the string path that I want. However, if I evaluate corgi-org-file-path after it is defined, I get a Python Traceback in the messages buffer:

Traceback (most recent call last):
  File \"<string>\", line 1, in <module>
ImportError: No module named config

I am not really sure what is happening here. What am I missing?

1

1 Answer 1

1

The cwd for that shell command will be based on the default-directory for the active buffer at the time your file is loaded; not the directory in which the loaded file resides.

You need to utilise the load-file-name variable.

(let ((default-directory (file-name-directory load-file-name)))
  (shell-command-to-string ...))
5
  • To make sure I understand what is going on: when I evaluate the shell-command-to-string part of the variable definition (using eval-last-sexp), the reason that it works as I expect is that I am currently in the same directory as the file (and thus my cwd is the right one). On the other hand, when I try to evaluate the variable itself on the next line in the same file, the reason it doesn't work is that the variable was actually defined earlier when the cwd was another directory. Is this what is happening?
    – elethan
    Commented Apr 25, 2016 at 12:40
  • I tried confirming this for myself by doing the above experiment, and then reevaluating the entire defvar (thinking that if I redefine the variable with the cwd as the correct one, it would work), but this had the same unexpected result. Your solution worked, but I am still confused as to why evaluating expression X has one result, but when I evaluate a variable that is set to the value returned by expression X I get a different result. I think this confusion is why I didn't see this as being a duplicate of my previous question, though the solution is the same
    – elethan
    Commented Apr 25, 2016 at 12:41
  • Re-evaluating the defvar for an already-defined variable does not change its value (it would not be possible to setq variables for not-yet-loaded libraries in your init file, otherwise, as loading the library would clobber your values). You could (makunbound 'VAR) first if you wanted to redefine VAR, though; or simply setq the new value.
    – phils
    Commented Apr 25, 2016 at 13:02
  • 1
    If it helps to clarify: Create a ~/pwd.el file containing (defvar my-cwd (shell-command-to-string "pwd")) (message "cwd: %s" my-cwd). Now start a new Emacs, visit some arbitrary file in any directory. Check C-h v default-directory and then M-x load-file RET ~/pwd.el RET and check the messages with C-h e. You'll see that the shell command was executed with cwd equal to the value of default-directory. Whatever triggers the loading of your library, the value of default-directory (which is always buffer-local) for the selected buffer at that time would be the shell command's cwd.
    – phils
    Commented Apr 25, 2016 at 13:51
  • Thank you for the detailed explanation! I think I have a better understanding of what is going on now. My problem is that I still haven't taken the time to sit down and really learn elisp, and just try to hack my way through whatever problems I need to solve without fully understanding what I am doing or what the consequences are, or why something works or doesn't work. However, through asking and answering questions on this site I am slowly getting there in spite of myself!
    – elethan
    Commented Apr 25, 2016 at 13:57

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