pycharm getpass在pychram IDE和终端中的行为不同

ohfgkhjo  于 2023-01-02  发布在  PyCharm
关注(0)|答案(1)|浏览(135)

paaword.py is a script where getpass() asked the user about the password and validates it. but i want to automate the whole process and used subprocess for it (main.py). And i am using python3.10
问题:
problem is when i run the main.py in pycharm IDE it works normally (it automates the process). but when I run the scriptpython3 main.pyin ubuntu terminal it asked for the input.
我不知道为什么它在IDE和终端中的行为不同?
password.py

import warnings
import getpass
import time

# Suppress warnings
warnings.filterwarnings("ignore", category=getpass.GetPassWarning)
for x in range(10):
    print(f"curnt index {x}")
time.sleep(5)
password = getpass.getpass("Enter your password: ")
if password != "test":
    print("wrong password")
else:
    print("correct password")

main.py

import subprocess

#  subprocess
proc = subprocess.Popen(["python", "password.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

password = "test"
input_data = f"{password}\n"

# read output from the subprocess in real-time
while True:
    if proc.poll() is not None:
        break

    proc.stdin.write(input_data.encode())
    proc.stdin.flush()

    output = proc.stdout.readline().decode().strip()
    if output:
        print(output)

pychar中的输出:

在ubuntu终端输出(20.04)

cbeh67ev

cbeh67ev1#

从屏幕截图来看,您的操作系统是Linux。
在Linux中,getpass()首先尝试直接从进程controlling terminal/dev/tty)读取,或者,如果失败,则使用直接终端I/O读取stdin;只有在失败时,它才返回到常规I/O,并显示警告。
从IDE中的警告判断,后者正是在第一种情况下发生的情况。
Lib/getpass.py

def unix_getpass(prompt='Password: ', stream=None):
    <...>
    try:
        # Always try reading and writing directly on the tty first.
        fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY)
        tty = io.FileIO(fd, 'w+')
        <...>
        input = io.TextIOWrapper(tty)
        <...>
    except OSError:
        # If that fails, see if stdin can be controlled.
        <...>
        try:
            fd = sys.stdin.fileno()
        except (AttributeError, ValueError):
            fd = None
            passwd = fallback_getpass(prompt, stream)    # fallback_getpass is what displays the warnings
        input = sys.stdin
        <...>
    if fd is not None:
        try:
            old = termios.tcgetattr(fd)
            <...>
        except termios.error:
            <...>
            passwd = fallback_getpass(prompt, stream)

    <...>
    return passwd

正如你所看到的,getpass()被特别设计成交互式的,并且可以防止拦截它的输入。所以如果你需要自动提供密码,使用另一种方法:

  • 将其存储在一个只有您可读的文件中(例如,SSH可以做到这一点;您可以将该文件作为参数提供,并在其中存储其他参数),或者
  • use the system's keyring
  • 并且只有在没有以这种方式提供密码和/或检测到程序正在交互式运行(sys.stdin.isatty())时才回退到getpass
  • 虽然也可以在命令行中提供密码--在这种情况下,您必须在进程的存储命令行中覆盖密码,以隐藏密码,使其不被窥探,但我在Python中找不到这样做的方法。

您可以查看Secure Password Handling in Python | Martin Heinz | Personal Website & Blog以获得上述内容的更详细的概要。(注意:它建议使用envars并从.env加载它们,这可能不适用于您。这是为. NET项目设计的,由于MS Visual Studio构建系统的僵化结构,这些项目必须依赖envars来获取任何变量值。)

相关问题