我正在编写一个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上运行。
答案 0 :(得分:0)
根据official documentation,getpass([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(打印到控制台),并且不会弄乱重定向的日志输出。