【问题标题】:How to connect Emacs' Elpy in-buffer python interpreter to docker container?如何将 Emacs 的 Elpy 缓冲区内 python 解释器连接到 docker 容器?
【发布时间】:2017-08-28 21:50:06
【问题描述】:

我开始开发将在 Docker 容器中运行的 Django 应用程序。我希望能够在 Emacs 中使用 interactive 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 时,它需要处理换行符,因此它会尝试使用编解码器文件。我认为这个文件不知何故依赖于临时文件,而 docker 容器把它搞砸了。我不知道这个理论有多接近,但我不知道如何进一步研究它。

【问题讨论】:

    标签: django python-3.x docker emacs elpy


    【解决方案1】:

    为什么 codecs.py 试图读取 tmp 文件?

    我很确定这是正在发生的事情:

    1. Emacs 将代码写入/tmp/py10324GOe
    2. Emacs 指示 Python 加载 /tmp/py10324GOe
    3. Python 失败,因为容器无法访问主机的/tmp/。容器有自己独立的 /tmp/ 目录。

    解决此问题的最简单方法是将主机的 /tmp/ 目录链接到容器的 /tmp/ 目录。一些谷歌搜索将我引向如下命令:

    docker run ... -v /tmp:/tmp
    

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

    【讨论】:

      【解决方案2】:

      我通过修改 python-shell--save-temp-file 函数从 /usr/local/share/emacs/26.3/lisp/progmodes/python.el.gz

      (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 是必要的
      猜你喜欢
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 2019-01-25
      • 2021-07-31
      • 2020-02-29
      • 2018-07-17
      • 2021-12-08
      • 2019-01-12
      相关资源
      最近更新 更多