在 Python 脚本中检查交互式 shell

Posted

技术标签:

【中文标题】在 Python 脚本中检查交互式 shell【英文标题】:Checking for interactive shell in a Python script 【发布时间】:2011-08-31 18:54:51 【问题描述】:

我需要确定调用我的 Python 脚本的 shell 是否处于交互模式。如果它处于交互模式,程序应该通过管道输出到 less(1) 以便于阅读。如果没有,它应该简单地将其输出打印到标准输出,以便将其通过管道传送到打印机、文件或不同的寻呼机。

在 shell 脚本中,我会检查提示变量 $PS1 是否已定义,或者在 $- 变量中存储的标志中查找 -i 选项。

在 Python 中测试交互性的首选方法是什么?

【问题讨论】:

【参考方案1】:

这通常效果很好

import os, sys
if os.isatty(sys.stdout.fileno()):
    ...

【讨论】:

sys.stdout.isatty() 更短。 sys.__stdin__.isatty() 更可靠。 (不受stdin 重定向的影响并允许输出) @Evpok:OP 要求 stdout,stdin 完全不相关。为了确定是否要分页 output,stdin 确实是要检查的错误流,因为用户可以将某些内容通过管道传输到程序中(因此重定向 stdin 并将其与 tty 断开连接)并且仍然想在寻呼机中查看输出(因为 stdout 没有被重定向)。 @Evpok,你是说sys.__stdout__.isatty()。当输入不是时,输出可能是 tty,并且 OP 似乎对输出感兴趣 @lunaryom 是的,我知道。但他确实写了“如果它处于交互模式,程序应该通过管道输出到 less(1) 以便于阅读”对我来说这意味着他检查stdin 并根据它的性质重定向stdout。跨度> 【参考方案2】:

从this link,您可以使用相同的方式并测试标准输入是否与终止(tty)相关联,您可以使用os.isatty() 执行此操作,例如:

>>> os.isatty(0)
True

注意:当您通过 ssh 远程调用命令时,从同一个链接这将失败,给出的解决方案是测试标准输入是否与管道相关联。

【讨论】:

我更喜欢更明显的sys.__stdin__.isatty() @Evpok:是的,同意,我忘记了文件对象方法 isatty(),谢谢 :) 这似乎等同于 gnibbler 的回答,只是读者必须知道足够多的 unix 才能知道文件 0 是标准输入。在标准输入或标准输出上检查 isatty() 有区别吗? @jforberg:是的,同意,我认为最好的是@Evpok 评论,sys.__stdin__.isatty(),AFAIK 交互模式意味着标准输入与终端相关联而不是标准输出,如果我错了,请纠正我: ) 是的,Evpok 的解决方案在我看来是最优雅和可读的。谢谢!【参考方案3】:

如果您已经依赖于 matplotlib,或者您不介意引入一个,您可以随时致电 matplotlib.is_interactive()

【讨论】:

查看 github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/… 的第 1049 行。 is_interactive() 只是读取 matplotlib 中的一个全局变量。我看不出它会引用父 shell 的交互性。【参考方案4】:
if sys.flags.interactive:
    #interactive
else:
    #not interactive 

http://docs.python.org/library/sys.html#sys.flags

【讨论】:

只有在 Python 使用 -i 选项启动时才会产生 true。使用 -i 选项启动它会在脚本运行后将 Python 置于解释器模式。 sys.flags.interactive 不能用来判断当前shell环境的性质。【参考方案5】:

我为测试制作了一个封面类。

例如你有:

class SuperInteractiveClass(object):
   def get_data_from_stdin(self):
      '... a lot of code here ...'
   '... and a lot of other function'

我做了第二节课,只是为了测试

class TestSuperInteractiveClass(SuperInteractiveClass):
    prepared_data = []
    def add_prepared_data(self,data):
        self.prepared_data.append(data)
    def get_data_from_stdin(self):
          return self.prepared_data.pop(0)

【讨论】:

我不明白。这有什么意义?这如何检查调用者的交互性? 它没有,至少在我能理解的任何方面都没有。看来他已经实现了一个堆栈。

以上是关于在 Python 脚本中检查交互式 shell的主要内容,如果未能解决你的问题,请参考以下文章

如何用Python交互执行shell脚本

如何创建交互式Shell脚本对话框?

自动化shell脚本except与python的pexpect模块

创建交互式shell脚本对话框

Deno 中的交互式 shell

shell进交互式不退出