【问题标题】:How to redirect the raw_input to stderr and not stdout?如何将 raw_input 重定向到 stderr 而不是 stdout?
【发布时间】:2014-01-18 09:39:10
【问题描述】:

我想将stdout 重定向到一个文件。但这会影响raw_input。我需要将raw_input 的输出重定向到stderr 而不是stdout。我该怎么做?

【问题讨论】:

  • 玩转sys.stdoutsys.stderrsys.stdout

标签: python io python-2.x


【解决方案1】:

raw_input 的唯一问题是它将提示打印到标准输出。与其试图拦截它,为什么不自己打印提示,并在没有提示的情况下调用raw_input,它不会向标准输出打印任何内容?

def my_input(prompt=None):
    if prompt:
        sys.stderr.write(str(prompt))
    return raw_input()

如果你想用这个替换raw_input

import __builtin__
def raw_input(prompt=None):
    if prompt:
        sys.stderr.write(str(prompt))
    return __builtin__.raw_input()

(有关更多信息,请参阅__builtin__ 上的文档,raw_input 和其他 built-in functions 存储在其中的模块。您通常不必import 它,但文档中没有任何内容保证,所以最好是安全的……)

在 Python 3.2+ 中,模块被命名为 builtins 而不是 __builtin__。 (当然 3.x 一开始就没有raw_input,它被重命名为input,但同样的想法也可以用在那里。)

【讨论】:

  • 应该使用 sys.stderr.write(str(prompt)) 以使其行为更像raw_input
  • @falsetru:是的,我认为你是对的。但是对于您的编辑,__builtin__ 是正确的名称; __builtins__ 是模块级对象的 CPython 特定名称,它是 __builtin____builtin__.__dict__。但是,我不确定__builtins__ 是否保证在没有import 的情况下存在,所以我将添加它。
  • @falsetru:嗯,它存在于__main__,但尝试不同类型的模块(像sys 这样的内置模块,像cPickle 这样的C 扩展模块,Java 和.NET 导入,普通Python 模块比如pickle,两种包)。
  • 自 Python 3.2 起模块和命名空间重命名为builtins
  • @GingerPlusPlus:当然在 3.2+ 中也没有 raw_input 可以替换。 :) 但是,是的,值得一提。
【解决方案2】:

暂时将stdout重定向到stderr,然后恢复。

import sys

old_raw_input = raw_input
def raw_input(*args):
    old_stdout = sys.stdout
    try:
        sys.stdout = sys.stderr
        return old_raw_input(*args)
    finally:
        sys.stdout = old_stdout

【讨论】:

  • 有什么简单的方法可以做到这一点。
  • 你可以很容易地写一个上下文管理器,所以你可以写with swapping_stdout:。您可以轻松编写一个装饰器,将函数包装在 with 语句中。但是,如果这是您唯一要做的地方,那就不会更简单了。 (见here。)如果你想要一个通用的属性交换上下文,这很容易……但你必须将命名空间和属性名称作为字符串传递给它,比如with swapping_attr(sys, 'stdout', sys.stderr):,我不这样做认为是一种改进。 (MacroPy 可以让它变得更好,但我不会仅仅为此使用 MacroPy……)
  • 另外,针对这种特定情况的一个常见技巧是使用sys.__stdout__ 而不是隐藏old_stdout
  • @abarnert,感谢您的评论。我更新了使用sys.__old_stdout__ 的答案(未使用sys.__stdout__,因为在Python 3.x 中,已经有sys.__stdout__,即使这是Python-2.x 问题)
  • @falsetru: sys.__stdout__ 至少在 2.6+ 中存在(并已记录),而不仅仅是 3.x。它始终是程序开始时sys.stdout 的原始值。如果您有嵌套重定向(因为不是恢复外部重定向而是恢复原始标准输出),以这种方式使用它可能会很麻烦/危险,但是对于 OP 正在寻找的内容,我认为这很好。
【解决方案3】:

使用getpass

import getpass

value=getpass.getpass("Enter Name: ")
print(value)

这会将内容value 打印到stdout,将Enter Name: 打印到stderr。

经过测试并适用于 python 2.7 和 3.6。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-22
    • 2022-01-18
    • 2012-08-07
    • 2011-05-23
    • 2013-09-16
    • 2012-09-25
    • 2011-07-22
    • 2012-07-14
    相关资源
    最近更新 更多