7

Is there a method to set what buffer python-mode looks to for a running python process?

I have a babel block in org-mode like

#+BEGIN_SRC python :session session1
import os
os.uname()
#+END_SRC

I can run the block (C-cC-c). I get results and a new *session1* buffer.

But I want to tinker with the code in the block. So I open it in a new buffer with the cord C-C C-' and am in org-src-mode ("OrgSrc") and python major mode (C-h b shows, for example, bindings for python-shell-send-region). However, attempting to use these bindings instead throws the warning:

Start a python process first with 'M-x run-python' or 'C-c C-p'.

Python is running, but it's in *session1*. If I do not name the :session the buffer is *Python* and all works as expected.

And, if i follow the run-python suggestion, a new *Python* buffer is created which is obviously not the same session in which the first execution occurred.

In addition to potentially having a need for separate sessions on a single host, I am tinkering with this simplified example in an effort to have a more usable python mode when interacting with tramp/:dir. e.g.

#+BEGIN_SRC python :session :dir /HostB:/tmp/
import os
os.uname()
#+END_SRC

I've also tried ob-ipython but I'm not sure configuring it to work with remote hosts is feasible.

3 Answers 3

7

This is really hidden and (to my knowledge) not documented so caveat emptor …

At the very end of org-edit-src-code I found the following snippet:

(let ((edit-prep-func (intern (concat "org-babel-edit-prep:" lang))))
  (when (fboundp edit-prep-func)
    (funcall edit-prep-func babel-info)))

This means you can define your own function org-babel-edit-prep:python and it will get executed after the Org Src buffer has been set up. It will receive as argument babel-info which is (per the doc string for org-babel-get-src-block-info) a list like (language body arguments switches name start coderef).

So … I use the following code to tell the new buffer where to look for the python process:

(defun org-babel-edit-prep:python (babel-info)
  "Set the buffer-local value of `python-shell-buffer-name' based
  on the :session header."
  (let* ((babel-args (nth 2 babel-info))
         (session (alist-get :session babel-args)))
    (when (string-match "\\*\\(.*\\)\\*" session)
      (setq-local python-shell-buffer-name (match-string 1 session)))))

NOTE: I haven't tested this with remote connections, though I assume something similar could be made to work.

0

The best workaround I've found so far is isend-mode. No python completion or inspection, but at least lines are easily sent to the REPL (isend-send/C-RET)

0

I've found a much simpler (if somewhat more primitive) solution:

If you use pyvenv in your sessions like I do, and already need to have an emacs-lisp block before your python sessions anyways, it's pretty easy to just do something like this:

#+begin_src emacs-lisp :session session1
  (pyvenv-activate "~/foo/path_to_my_venv")
  (setq python-shell-buffer-name "session1")
#+end_src

#+begin_src python :session session1
  import os
  os.uname()
#+end_src

Your Answer

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

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