从Emacs运行交互式Python脚本

9 投票
6 回答
10658 浏览
提问于 2025-04-17 13:10

我对vim还算熟练,但我的朋友们跟我说了很多关于emacs的好处,所以我决定试试这个编辑器,尤其是在听说了它的“evil模式”之后……

现在,我正在写一个需要用户输入的python脚本(这是cmd.Cmd的一个子类)。在vim里,如果我想试一下这个脚本,我可以简单地输入 :!python %,然后就可以和我的脚本互动,直到它退出为止。在emacs里,我试着用 M-! python script.py,这确实会在一个新的窗口中运行脚本,但按下回车键似乎没有传回脚本,而是被emacs的窗口捕获了。我还试着查看python-mode的 C-c C-c,但这个命令会在一个临时目录中运行脚本,而我只是想在 (pwd) 这个目录下运行它。

那么,有没有什么标准的方法可以做到这一点呢?

6 个回答

3

我现在使用这些钩子来定义我的编译命令:

(defun convert-filename-to-executable (file)
  (if (eq system-type 'windows-nt)
      (concat (file-name-sans-extension file) ".exe")
    ;; linux
    (concat "./" (file-name-sans-extension file))))


(add-hook 'c++-mode-hook
          (lambda ()
            (unless (file-exists-p "Makefile")
              (set (make-local-variable 'compile-command)
                   (let* ((file (file-name-nondirectory buffer-    file-name))
                      (executable (convert-filename-to-executable file)))
                 (concat "g++ -g -Wall -o "
                         (file-name-sans-extension file)
                         " "
                         file
                         " && "
                         executable))))))

(add-hook 'c-mode-hook
      (lambda ()
        (unless (file-exists-p "Makefile")
          (set (make-local-variable 'compile-command)
               (let* ((file (file-name-nondirectory buffer-file-name))
                      (executable (convert-filename-to-executable file)))
                 (concat "gcc -g -ansi -Wall -Wpedantic -Wextra -Wc++-compat -Wconversion -o "
                         (file-name-sans-extension file)
                         " "
                         file
                         " && "
                         executable))))))    
(add-hook 'python-mode-hook
          (lambda ()
              (set (make-local-variable 'compile-command)
                   (concat "python " buffer-file-name))))

(add-hook 'perl-mode-hook
          (lambda ()
              (set (make-local-variable 'compile-command)
                   (concat "python " buffer-file-name))))

还有这个 lambda 函数,用来互动地调用编译功能:

(global-set-key (kbd "<f4>") (lambda () (interactive) (setq current-prefix-arg '(4)) (call-interactively 'compile)))

一个按钮统治所有!

如果你按下 F4(在我的情况下,你可以在 lambda 中为 global-set-key 设置这个按键),那么在 C++ 或 C 模式下打开的文件会被编译,而在 Python 或 Perl 模式下的文件会被运行(以互动方式)

3

我喜欢用Emacs里的“编译”命令来测试或运行我的Python脚本。你可以按 M-X 然后输入 compileRET,这时会出现默认的“make -k”命令。如果你把这个命令删掉,换成你自己脚本的命令(包括选项),那么之后每次再用“编译”时,它会自动记住你输入的新命令。你脚本的所有输出都会显示在编译缓冲区里。这样比在终端里运行要好,因为每次调用时都有一个干净的界面,方便查找信息。如果你在运行之前忘记保存脚本,编译命令会问你是否要保存文件。

不过,当你重启Emacs时,你之前输入的命令会丢失。但是你可以在Python脚本的底部加上一段代码(其实是Python的注释),让Emacs为这个脚本的缓冲区设置编译命令:

 # Trigger emacs to run this script using the "compile" command
 # ;;; Local Variables: ***
 # ;;; compile-command: "my_cool_script.py --complicated_option some_filename.txt" ***
 # ;;; end: ***

这样对于那些调用比较复杂的脚本来说就很方便了。注意:Python的注释符号‘#’可以让这段代码不被Python解释器执行,而Emacs会在打开文件时查看每个文件的底部,从而知道设置这些变量。

我希望能像编译C代码时那样,直接跳到Python脚本中的“编译错误”位置,但我懒得去写Emacs的正则表达式来实现这个功能。也许这可以成为Stack Overflow上的另一个好问题!

4

我对canonical不太了解,但如果我需要和一个脚本互动,我会按下 M-x,然后输入 shell,再按 RET,这样就可以从那里运行脚本了。

还有一个更强大的功能叫 M-x terminal-emulator,它可以模拟终端,不仅仅是处理一些简单的命令。

撰写回答