将输出重定向到文件

时间:2020-03-17 17:52:45

标签: python

我正在编写一个CLI,它接受用于身份验证的电子邮件和密码。 电子邮件提示使用raw_input(),密码提示使用getpass()进行混淆。

直接输出到控制台时,此设置可以正常工作,但是将输出重定向到日志文件时,此设置会失败。

示例代码:

    user_email = raw_input('Email: ')
    user_password = getpass('Password: ')

不带重定向的示例输出:

$ python script_that_does_stuff.py

Email: me@email.com
Password: 

Doing stuff...

带有重定向的示例输出:

$ python script_that_does_stuff.py > stuff.log

因为我知道希望在这里输入用户信息,所以我可以输入电子邮件,按回车键,然后它将显示:

$ python script_that_does_stuff.py > stuff.log
me@email.com
Password: 

输入密码后,密码照常继续,但是日志显示以下内容:

$ cat stuff.log

Email:Doing stuff...

问题:

在将输出重定向到文件时,如何强制raw_input()提示符像getpass()提示符一样在控制台中显示?

环境

此脚本存在于旧版Python 2.7代码库中,主要在Mac OS系统上运行,有时在Linux上运行。

3 个答案:

答案 0 :(得分:0)

根据official documentationgetpass([prompt[, stream]])具有第二个可选参数,该参数指示将提示打印到的输出流(默认为stderr)。

当您重定向输出(stdout时,对于stderr的提示仍会打印到getpass,但是raw_input不支持设置输出流,因此其提示正在重定向到目标文件。

因此,要解决您的问题,您还必须将提示也打印到stderr上以接收电子邮件。

答案 1 :(得分:0)

您可以暂时覆盖sys.stdout以写入终端。例如,

import contextlib
import sys


@contextlib.contextmanager
def output_to_terminal():
    try:
        with open("/dev/tty") as f:
            sys.stdout = f
            yield
    finally:
        # Ensure sys.stdout is restored in the event of an error
        sys.stdout = sys.__stdout__


with output_to_terminal():
    x = raw_input("> ")
print(x)

(这是独立派生的;您可能想检查同样在redirect_stdout模块中找到的Python 3的contextlib的源代码,并将其回移植以供使用。)

答案 2 :(得分:0)

This answer在另一个问题上似乎对我有用。

简而言之,创建一个自定义输入函数:

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

然后,调用代码变为:

    user_email = email_input('Email: ')
    user_password = getpass('Password: ')

这导致将电子邮件和密码提示发送到stderr(打印到控制台),并且不会弄乱重定向的日志输出。