getpass在PyCharm与终端中行为差异及自动化执行问题
问题
我有一个用getpass()获取并验证密码的Python脚本password.py,通过main.py调用subprocess实现自动化执行,用的是Python 3.10版本。在PyCharm里跑main.py能正常自动完成流程,但在Ubuntu 20.04终端执行python3 main.py时,脚本还是会弹出要求手动输入密码,搞不懂为啥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 proc = subprocess.Popen(["python", "password.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) password = "test" input_data = f"{password}\n" # 实时读取子进程输出 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)
原因分析与解决办法
- 问题根源:
getpass.getpass()在真实终端环境下,默认会直接读取终端设备(/dev/tty)的输入,完全绕开你通过subprocess.PIPE传入的标准输入。PyCharm的模拟终端会把子进程的终端输入重定向到IDE的标准输入,所以getpass能拿到你传入的密码;但在Ubuntu真实终端里,getpass会直接和终端交互,无视管道传递的内容,因此会要求手动输入。
方案一:修改main.py的子进程调用逻辑
重定向所有流并调整输入时机,避免重复写入密码:
import subprocess # 重定向stdin、stdout、stderr,使用文本模式简化编码解码 proc = subprocess.Popen( ["python3", "password.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) password = "test" input_data = f"{password}\n" # 先读取脚本循环打印的10行内容 for _ in range(10): line = proc.stdout.readline() if line: print(line.strip()) # 等待sleep完成后,写入密码 proc.stdin.write(input_data) proc.stdin.flush() # 读取密码验证后的输出 while True: line = proc.stdout.readline() if not line: break print(line.strip()) # 读取getpass的提示信息(输出在stderr) stderr_content = proc.stderr.read().strip() if stderr_content: print(stderr_content) proc.wait()
方案二:修改password.py支持自动化模式
添加命令行参数判断,让脚本可以从标准输入读取密码:
import warnings import getpass import time import sys # Suppress warnings warnings.filterwarnings("ignore", category=getpass.GetPassWarning) for x in range(10): print(f"curnt index {x}") time.sleep(5) # 传--auto参数时从stdin读取密码,否则用getpass if len(sys.argv) > 1 and sys.argv[1] == "--auto": password = sys.stdin.readline().strip() else: password = getpass.getpass("Enter your password: ") if password != "test": print("wrong password") else: print("correct password")
对应的main.py调用时加上参数:
import subprocess proc = subprocess.Popen( ["python3", "password.py", "--auto"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True ) password = "test" input_data = f"{password}\n" # 读取循环输出 for _ in range(10): line = proc.stdout.readline() if line: print(line.strip()) # 写入密码 proc.stdin.write(input_data) proc.stdin.flush() # 读取验证结果 while True: line = proc.stdout.readline() if not line: break print(line.strip()) proc.wait()
内容的提问来源于stack exchange,提问作者Rabia Hussain
相关产品推荐
相关产品推荐

