Python:将getpass与argparse一起使用



我四处看了看,但什么也找不到。

基本上我想知道是否可以将getpass.getpass()与 argparse 一起使用。

目前我有以下解决方法,我只是想知道是否有更好的方法:

import argparse
import getpass
parser = argparse.ArgumentParser(description="Some description")
parser.add_argument('-p', metavar="password", default="foobarblah123", help="password for user (default to prompt user)")
...
parsed_args = parser.parse_args()
args = vars(parsed_args)
user_pass = args['p']
if user_pass == "foobarblah123":
  user_pass = getpass.getpass()

我很确定这不是处理此问题的最佳方法,但是,需要为密码设置命令行选项......最佳实践与否。

谢谢。

我想

我可能已经找到了更好的方法。如何使用这样的自定义操作:

import argparse
import getpass
class PasswordPromptAction(argparse.Action):
    def __init__(self,
             option_strings,
             dest=None,
             nargs=0,
             default=None,
             required=False,
             type=None,
             metavar=None,
             help=None):
        super(PasswordPromptAction, self).__init__(
             option_strings=option_strings,
             dest=dest,
             nargs=nargs,
             default=default,
             required=required,
             metavar=metavar,
             type=type,
             help=help)
    def __call__(self, parser, args, values, option_string=None):
        password = getpass.getpass()
        setattr(args, self.dest, password)
parser.add_argument('-u', dest='user', type=str, required=True)
parser.add_argument('-p', dest='password', action=PasswordPromptAction, type=str, required=True)
args = parser.parse_args()

环顾四周,没有找到足够的解决方案。 这是我想到的。

from argparse import ArgumentParser
from getpass import getpass
def main():
    parser = ArgumentParser(description="arg parser hidden password input.")
    parser.add_argument('-sp', '--secure_password', action='store_true', dest='password', 
                        help='hidden password prompt')
    args=parser.parse_args()
    if args.password:
        password = getpass()
    print(password)
if __name__ == "__main__":
    main()

显然,您会想要删除print(password),这只是为了验证其是否有效而添加的。

以下是我想出的提示输入非常小的密码(Python 3 代码):

import argparse
import getpass

class Password:
    DEFAULT = 'Prompt if not specified'
    def __init__(self, value):
        if value == self.DEFAULT:
            value = getpass.getpass('LDAP Password: ')
        self.value = value
    def __str__(self):
        return self.value

parser = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-u', '--username', help='Specify username',
    default=getpass.getuser())
parser.add_argument('-p', '--password', type=Password, help='Specify password',
    default=Password.DEFAULT)
args = parser.parse_args()
print(args.username, args.password)

使用示例:

$ python ~/Desktop/example.py -h
usage: example.py [-h] [-u USERNAME] [-p PASSWORD]
optional arguments:
  -h, --help            show this help message and exit
  -u USERNAME, --username USERNAME
                        Specify username (default: gavinr)
  -p PASSWORD, --password PASSWORD
                        Specify password (default: Prompt if not specified)
$ python ~/Desktop/example.py -p foo
gavinr foo
$ python ~/Desktop/example.py 
LDAP Password: 
gavinr foo

根据Rares Musina的回答,我注意到一个缺点:在命令行上提交密码时,提示符不断出现。当通过提示符提供密码时,argparse 会将命令行上已经给出的密码视为另一个参数(很可能不存在)。

在理想情况下,这是预期行为:

    命令行
  • 上未给出任何值时的密码提示
  • 在命令行上给出值时没有提示

这两种情况都应被接受。理想情况下,第二种情况应发出安全警告。

nargs设置为 '?' 时,它需要零个或一个参数。这使得它可以选择通过命令行提供密码。

因此,将"add_argument"更改为:

arg_parser.add_argument("-p", "--password", type=str, action=PasswordPromptAction, nargs='?')

应编辑PasswordPromptAction以加以区分。'values' 参数包含在命令行上给出的值(如果给定了一个):

class PasswordPromptAction(argparse.Action):
    def __call__(self, parser, args, values, option_string=None):
        # If no value is given on the commandline prompt for password.
        if values:
            # Ideally a security warning could be generated here.
            setattr(args, self.dest, values)
        else:
            setattr(args, self.dest, getpass.getpass())

现在支持以下用法:

python program.py -p
python program.py -p p@ssw0rd

如果未在命令中指定密码,这将使用 getpass() 提示。很好,因为它支持自动脚本和手动使用隐藏密码。

import argparse
from getpass import getpass
parser = argparse.ArgumentParser(description="specify or prompt for a hidden password.")
parser.add_argument('-p', '--password', required=False, type=str)
args = parser.parse_args()
if not args.password: 
    args.password = getpass()
我喜欢

这个解决方案,因为用户可以同时传递:

$> python program.py login -u user1 -p pass1

或仅一个:

$> python program.py login -u user1

或任何:

$> python program.py 登录

如果参数未传递用户或密码,则以交互方式请求。

import argparse
import getpass
def parse_args():
    parser = argparse.ArgumentParser(description="command line client")
    subparser = parser.add_subparsers(dest='command', metavar='command')
    subparser.required = True
    parser.set_defaults(funct=argparser_handler)
    # Login
    sub_parser = subparser.add_parser("login", help="Login with email and password")
    sub_parser.add_argument('-u', dest='user', help='user.  If this argument is not passed it will be requested.')
    sub_parser.add_argument('-p', dest='password', help='password.  If this argument is not passed it will be requested.')
    args = parser.parse_args()
    args.funct(args)
def argparser_handler(args):
    if (args.command == 'login'):
        login(args.user, args.password)

def login(user, password):
    if not user:
        user = input("User:") 
    if not password:
        password = getpass.getpass()    
    print("user:", user)
    print("password:", password)

def main():
    pass
if __name__ == '__main__':
    parse_args()
    main()

最新更新