我正在编写的一系列应用程序要求用户能够使用KLOG身份验证从文件系统中读取。某些功能要求用户具有KLOG令牌(即,被认证)而其他功能则不需要。我写了一个小的Python装饰器,以便我可以在我的模块中重构“你必须被KLOGed”功能:
# this decorator is defined in ``mymodule.utils.decorators``
def require_klog(method):
def require_klog_wrapper(*args, **kwargs):
# run the ``tokens`` program to see if we have KLOG tokens
out = subprocess.Popen('tokens', stdout=subprocess.PIPE)
# the tokens (if any) are located in lines 4:n-1
tokens_list = out.stdout.readlines()[3:-1]
if tokens_list == []:
# this is where I launch KLOG (if the user is not authenticated)
subprocess.Popen('klog')
out = method(*args, **kwargs)
return out
return require_klog_wrapper
# once the decorator is defined, any function can use it as follows:
from mymodule.utils.decorators import require_klog
@require_klog
def my_function():
# do something (if not KLOGed, it SHUOLD ask for the password... but it does not!)
这一切都很简单。除非我尝试应用以下逻辑:“如果用户不是KLOG,请运行KLOG并要求输入密码”。
我使用subprocess.Popen('klog')
执行此操作,password:
提示符出现在终端上。但是,当我写密码时,它实际上会回显给终端,更糟糕的是,在返回时没有任何反应。
编辑:
在Alex快速正确的回答之后,我解决了以下问题:
*.pyc
文件(是的 - 这有所不同)getpass.getpass()
将密码存储在本地变量-pipe
选项write
方法以下是修正后的装饰者:
def require_klog(method):
def require_klog_wrapper(*args, **kwargs):
# run the ``tokens`` program to see if we have KLOG tokens
out = subprocess.Popen('tokens', stdout=subprocess.PIPE)
# the tokens (if any) are located in lines 4:n-1
tokens_list = out.stdout.readlines()[3:-1]
if tokens_list == []:
args = ['klog', '-pipe']
# this is the custom pwd prompt
pwd = getpass.getpass('Type in your AFS password: ')
pipe = subprocess.Popen(args, stdin=subprocess.PIPE)
# here is where the password is sent to the program
pipe.stdin.write(pwd)
return method(*args, **kwargs)
return require_klog_wrapper
答案 0 :(得分:2)
显然,您的脚本(或稍后产生的其他内容)和运行klog
的子进程正在“竞争”/dev/tty
- 并且子流程正在丢失(毕竟,您不是调用从wait
返回的对象的subprocess.Popen
方法,以确保在继续之前等到它终止,因此某种竞争条件不会令人感到意外。
如果wait
不够,我会通过添加
pwd = getpass.getpass('password:')
Python代码中的(当然在顶部有import getpass
),然后使用klog
参数和-pipe
运行stdin=subprocess.PIPE
,并编写pwd
到该管道(调用从subprocess.Popen
返回的对象的communicate方法。)