判断Python是否处于交互模式

71
在Python脚本中,有没有办法判断解释器是否处于交互模式?这将非常有用,例如当您运行交互式Python会话并导入模块时,会执行略有不同的代码(例如关闭日志记录)。我查看了tell whether python is in -i mode并尝试了那里的代码,但是该函数仅在Python使用-i标志调用时返回true,并且当用于不带参数的python调用交互模式时不返回true。我的意思是像这样的东西:
if __name__=="__main__":
    #do stuff
elif __pythonIsInteractive__:
    #do other stuff
else:
    exit()

考虑在库中使用“logging”模块进行日志记录,以便用户可以使用共享配置来控制它。 - Bachsau
7个回答

70

__main__.__file__在交互式解释器中不存在:

import __main__ as main
print hasattr(main, '__file__')

对于通过 python -c 运行的代码也适用,但不适用于 python -m


5
例如,在py2exe可执行文件中也是如此。 - fmark
6
很不幸,这在嵌入式shell中不起作用。也就是说,在使用IPython.embed()启动的shell中无法使用该功能。 - titusjan
9
bool(getattr(sys, 'ps1', sys.flags.interactive)) 可以翻译为:判断当前是否在交互模式下运行Python,适用于Python2.6及以上版本。 - Mr. B
1
到目前为止,似乎没有任何解决方案能够检测到 PYTHONSTARTUP=script.py python3。表达式 'readline' in sys.modules 可以,以及 python3 -i script.pypython3 -ic 'import script'(在 Ubuntu focal 上测试了 Python 3.8.2),但这些方法高度不可移植。 - photon.engine
这是唯一适用于通过 python -m ptpython 启动的 ptpython 交互会话的有效答案。 - JamesThomasMoon

51

我比较了所有找到的方法,并制作了一个结果表。最好的方法似乎是这个:

hasattr(sys, 'ps1')

在此输入图片描述

如果有其他可能不同的情况,请留言,我将进行添加。


1
嘿,感谢您的辛勤工作,您能否检查一下Windows、Linux和Mac哪个更好? - Fred Dufresne
在 Windows 11 上,PyCharm 2022.1.4 (CE) 控制台中 hasattr(sys, 'ps1') 返回 False - N. Maks
我忘了提到解释器是Python 3.10.6。 - N. Maks

29

@Keith 在我的 iPython 3.2.1 REPL 中使用 python 2.7.9 看起来运行良好。 - hobs
2
同意,我刚在4.0版本上检查了一下,那里也可以运行。可能是旧版IPython的问题。 - Keith Hughitt
在我看来,即使在非交互模式下运行iPython,sys.ps1sys.ps2也会被定义。 - Jasha

18

使用sys.flags

if sys.flags.interactive:
    #interactive
else:
    #not interactive 

14
这仅检查命令行参数 python -i,而不是通过键入 python 单独进入Python交互模式的测试。 - the wolf
10
bool(getattr(sys, 'ps1', sys.flags.interactive)) 可以翻译为:检查当前 Python 解释器是否运行在交互式模式下,结果为布尔值。 - Mr. B

7

来自TFM:如果没有给出接口选项,则会暗示-i,sys.argv [0]是一个空字符串(“”),并且当前目录将添加到sys.path的开头。

如果用户使用python而没有参数调用解释器,就像您提到的那样,您可以使用if sys.argv [0] ==''进行测试。如果使用python -i启动,它也将返回true,但根据文档,它们在功能上是相同的。


1
哎呀,直接违反了Python之禅 :) - Tim Pietzcker
嘿...虽然我认为@echoback的版本是唯一明显的(有点)版本。我之所以没有接受它,只是因为在C等语言中,理论上argv[0]可能为NULL或空字符串,而我不想调试由此引起的任何潜在错误... - Chinmay Kanchi
5
然而,这可能会给其他解释器带来问题。例如,在使用IPython时,sys.argv = ['/usr/bin/ipython']。 - Keith Hughitt

1
以下内容无论是否使用-i开关都有效:
#!/usr/bin/python
import sys
# Set the interpreter bool
try:
    if sys.ps1: interpreter = True
except AttributeError:
    interpreter = False
    if sys.flags.interactive: interpreter = True

# Use the interpreter bool
if interpreter: print 'We are in the Interpreter'
else: print 'We are running from the command line'

1
if sys.ps1: interpreter = True => interpreter = sys.ps1 或者 interpreter = bool(sys.ps1) - Cristian Ciupitu
@CristianCiupitu:在发布代码之前,您可能需要先对其进行测试。即使它是有效的Python代码,在从命令行运行时也会抛出AttribeError异常。 - jdines
1
抱歉我说话有点含糊,但我不明白为什么27个字符比30个字符更长,或者为什么if语句需要sys.ps1的布尔值时会更加计算密集。 - Cristian Ciupitu
你说的不一致是正确的,这就是为什么我提出了第二个变体。我有python-2.7.5-13.fc20.x86_64和相应的pyc,确实使用bool变量时更大了5个字节。但是如果我还将except代码更改为interpreter = bool(sys.flags.interactive),那么文件会减小27个字节:-D - Cristian Ciupitu
2
NECROMANCY!:bool(getattr(sys,'ps1',sys.flags.interactive)) - Mr. B
显示剩余3条评论

-4

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