如何将Emacs的Elpy内置的Python解释器连接到Docker容器?

9
我开始着手开发一个在Docker容器中运行的Django应用程序。我希望能够在Emacs中使用交互式Python,以在Docker容器和Django应用程序的上下文中执行代码。基本上,我希望由Emacs使用的Python解释器在Docker容器中运行。
我已经成功地实现了这一点,通过创建一个修改后的Dockerfile,该文件与我的实际Dockerfile容器不同之处仅在于它不是调用Django命令,而是以以下方式结束:
CMD ./manage.py shell

这意味着当我运行该Docker容器时,我会得到一个实际在容器内运行的Django解释器。 我通过添加以下内容使Elpy在启动python shell时调用它:
(setq python-shell-interpreter "/path_to_my_script/run_shell.sh")

将文本翻译为中文:

添加到我的.emacs.d/init.el文件中。其中"/path_to_my_script/run_shell.sh"脚本是运行容器的脚本。

实际上,这在大部分情况下都有效。我能够突出显示代码行,例如:

from django.utils import timezone

运行Emacs命令 elpy-shell-send-region-or-buffer,然后它将执行代码。然后我可以突出显示。
print(timezone.now())

"并且它将打印当前时间。我已经验证了这段代码确实在我的容器上运行,方法是运行:"
import os
print(os.getcwd())

“以及查看我的Docker容器用户的主目录。”
“我在这个设置中仍然遇到的问题是,当我尝试使用相同的elpy-shell-send-region-or-buffer命令同时执行多行python时。当我突出显示多于一行并执行该命令时,我会在python shell中收到以下错误:”
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.5/codecs.py", line 895, in open
    file = builtins.open(filename, mode, buffering)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/py10324GOe'

我一直无法找到以下问题的答案:
  • 为什么codecs.py要读取一个tmp文件?
  • Python创建的所有临时文件是用来做什么的?(如果你有一些Python代码在运行,并查看你的 /tmp 目录,你可能会看到很多像 py271761jE 这样的文件。)
  • 为什么我的Docker容器中的 /tmp 目录是空的?似乎Python想要在该目录中创建和读取文件,但失败了。
  • 我该如何调试这个问题?

如果有人对这些问题有任何答案,那将是一个巨大的帮助。我一直无法找到关于这个问题的任何信息。在 /tmp 目录中搜索py*文件只会出现tempfile包的结果。

我不知道发生了什么,但我目前的理论是当一个具有多行的区域发送到Python shell时,它需要处理换行符,因此尝试使用codecs文件。我认为这个文件某种程度上依赖于临时文件,而Docker容器正在破坏它。我不知道这个理论有多接近,但我不知道如何进一步调查它。

2个回答

6
为什么codecs.py要读取一个临时文件?
我非常确定是这个问题正在发生:
1. Emacs将代码写入/tmp/py10324GOe中 2. Emacs指示Python加载/tmp/py10324GOe 3. Python失败,因为容器无法访问主机的/tmp/。容器有自己独立的/tmp/目录。
最简单的修复方法是将主机的/tmp/目录链接到容器的/tmp/目录。一些谷歌搜索引导我使用如下命令:
docker run ... -v /tmp:/tmp

我没有测试过那段代码,但它似乎是正确的方向。


0

我通过修改/usr/local/share/emacs/26.3/lisp/progmodes/python.el.gz中的python-shell--save-temp-file函数取得了一些成功。

(defun python-shell--save-temp-file (string)
  (let* ((temporary-file-directory
          (if (file-remote-p default-directory)
              (concat (file-remote-p default-directory) "/tmp")
            temporary-file-directory))
         (temp-file-name (make-temp-file "py"))
         (coding-system-for-write (python-info-encoding)))
    ;; vvvv asychronous won't work ;;; change ownership of the tmp file to the user firing python proc                                           
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; inside the container and                                                                                  
    (call-process "docker"  nil nil nil "exec" "-u" "root" "mycontainer" "chown" "pythonuser:"  temp-file-name)
    (call-process "docker"  nil nil nil "exec" "-u" "root" "mycontainer" "chmod" "606"  temp-file-name)
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; my user on the host need also access to that file so o+rw                                                
    (with-temp-file temp-file-name
      (insert string)
      (delete-trailing-whitespace))
    temp-file-name))

希望有人能提供一个更聪明的解决方案。

哦!正如@BrianMalehorn所说,挂载/tmp是必要的。 - azyzy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接