4

If I use tramp to open a remote file, and subsequently run run-python, it tries to execute in the remote context (which is not what I want and super slow).

Any way of specifying a local context or disabling this behaviour?

Daniel Mahler
  • 267
  • 1
  • 12
EoghanM
  • 205
  • 1
  • 4

2 Answers2

2
(defun run-python-locally (&rest args)
  (interactive (progn (require 'nadvice)
                      (advice-eval-interactive-spec
                       (cadr (interactive-form #'run-python)))))
  (let ((default-directory user-emacs-directory))
    (apply #'run-python args)))

(This uses the trick from this answer).

Additionally, if you'd like to use python-shell-send-string, python-shell-send-region and company, you'll need this fix:

(eval-when-compile (require 'cl-lib))
(defun nadvice/python-shell-send-string/fix-local-process
    (old-fun string &optional process)
  (cl-letf* ((old-psstf (symbol-function #'python-shell--save-temp-file))
             ((symbol-function #'python-shell--save-temp-file)
              (lambda (string)
                (let ((default-directory
                        ;; if buffer is a remote file, but the process is not
                        ;; save the temp file locally, instead of remotely
                        (if (and buffer-file-name
                                 (file-remote-p buffer-file-name)
                                 (not (plist-get (process-plist process)
                                                 'remote-tty)))
                            user-emacs-directory
                          default-directory)))
                  (funcall old-psstf string)))))
    (funcall old-fun string process)))

(advice-add 'python-shell-send-string :around
            #'nadvice/python-shell-send-string/fix-local-process)
PythonNut
  • 10,243
  • 2
  • 29
  • 75
  • Nice! That automates what I was suggesting. – Daniel Mahler Mar 16 '16 at 21:10
  • I would probably make it a separate command though, rather then changing the behaviour of `run-python` itself. The default behaviour is useful most of the time. – Daniel Mahler Mar 16 '16 at 21:13
  • It may appear that I'm changing the definition of `run-python` because I'm using a function from `nadvice`, but I'm not. `run-python-locally` is a new, separate command, which doesn't modify the behavior of `run-python`. – PythonNut Mar 16 '16 at 21:15
  • Thanks. I thought nadvice was related to the advice mechanism. I will have to look it up. – Daniel Mahler Mar 16 '16 at 21:18
  • @DanielMahler it is, but in this case I'm using it to duplicate the interactive-spec of `run-python` for my command, ensuring that future modifications won't break this function. This isn't an incantation you'll see very often, but I think it's very handy. – PythonNut Mar 16 '16 at 21:20
  • This does not make `eval-buffer` work for the remote file either, right? – Daniel Mahler Mar 16 '16 at 21:22
  • @DanielMahler re: `eval-buffer`. No, it does not. I'll take a look into it, but I can't promise anything. – PythonNut Mar 16 '16 at 21:24
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/37081/discussion-between-pythonnut-and-daniel-mahler). – PythonNut Mar 16 '16 at 21:27
  • 1
    @DanielMahler this now works with the various process interaction functions. – PythonNut Mar 17 '16 at 00:00
  • Cool! I've it bound to `run-py` so that I'm more likely to call it than the remote version – EoghanM Mar 21 '16 at 16:39
1

You can start a local python console by executing run-python while in a local buffer (*scratch* will do). The problem is that python interaction will not work for remote files then without some additional hacking. Generally you need the python process to be running on the same machine that the files reside on since emacs communicates with the python process vial the file system.

For example python-shell-send-buffer saves a copy of the buffer in /tmp for the process to read. With a remote file and a local python process the buffer will get saved to on the remote machine and python will try to read from the same path on the local one and fail to find it.

To make python interaction work with files on a different machine from where the python shell is running would require tweaking the code to put temporary files on the machine where the python is running, regardless of where the file is, or where you are running emacs. I would be interested to know how to do that myself.

Daniel Mahler
  • 267
  • 1
  • 12
  • Sometimes I just want to dive into the Python console to use as a calculator. – EoghanM Mar 16 '16 at 14:35
  • @EoghanM executing `run-python` from `*scratch*` or another local buffer will give you that. You could even put `(run-python)` in your .emacs or init.el. For that use I also really recommend setting `(custom-set-variables '(python-shell-interpreter "ipython") '(python-shell-interpreter-args "--pylab"))` It will give you `numpy` and `matplotlib.pyplot` in your global namespace as well as all the benefits of IPython – Daniel Mahler Mar 16 '16 at 21:01