Emacs中的Python: __name__ == '__main__',但似乎不是

13 投票
3 回答
2033 浏览
提问于 2025-04-18 06:31

我在emacs里写Python代码,但有时候emacs里的Python解释器让我感到意外。

如果我在emacs的一个窗口里写

print()
print(__name__)
print(__name__=='__main__')
if __name__ == '__main__':
    print("indeed")

然后让我emacs启动一个解释器并运行这个窗口里的内容,我得到的结果是

Python 3.3.5 (default, Mar 18 2014, 02:00:02) 
[GCC 4.2.1 20070831 patched [FreeBSD]] on freebsd9
Type "help", "copyright", "credits" or "license" for more information.
>>> 
__main__
True
>>> 

(这里的__main__True都是打印语句的输出;Python窗口总是显示>>>,然后立刻打印结果。我知道这一点,这不是问题。)

在命令行里,运行pythonpython -i都会如预期显示'indeed'。

那么,emacs是怎么做到在评估__name__=='__main__'时返回True,但却不执行if __name__ == '__main__':里面的内容的呢?我该怎么重新配置它,让它不再这样做呢?

3 个回答

0

一旦你启动了Python的命令行界面,你可以很简单地覆盖(也就是重新定义)一个变量:

__name__ = 'repl' 

这样做可以防止在后续使用 C-c C-c 命令时,任何 if __name__=='__main__': 这部分代码被执行。

2

这个“功能”永远不会过时。试着使用

__name__=='__main__':

在运算符之间不要留空格。

这样的话,python.el 就不会跳过它。所以看看你的代码格式化工具。

9

正如@Wooble在评论中提到的,这可能是python.el的问题:C-c C-c会运行
python-shell-send-buffer这个功能:

python-shell-send-buffer是一个在`python.el`中的交互式编译Lisp函数。

(python-shell-send-buffer &可选 ARG)

将整个缓冲区的内容发送到一个Python进程。如果加上前缀ARG,就可以执行被"if __name__=='__main__':"包围的代码块。

也就是说,要打印“确实”,你需要加上前缀C-u C-c C-c

问:我试着查看python.el的代码,但仍然不确定它是如何以及在哪里做到这一点的。你能解释一下吗?这样我就可以修改默认行为。

要了解C-c C-c在你这边的作用,可以打开一个Python文件,然后输入M-x describe-key RET,接着按C-c C-c(实际上就是按下这些键)。默认情况下,它会在python.el中运行python-shell-send-buffer这个功能。你可以重新定义这些按键,让它们调用带参数的函数,这样C-c C-c就会像C-u C-c C-c那样,能够运行"if __name__=='__main__':"部分:

;; Make C-c C-c behave like C-u C-c C-c in Python mode
(require 'python)
(define-key python-mode-map (kbd "C-c C-c")
  (lambda () (interactive) (python-shell-send-buffer t)))

撰写回答