用过Linux的都知道,尤其是进行使用包管理软件类似于apt-get这种的,密码是不回显的。在一定程度上可以保护我们的密码不被旁边的人看到,保护个人的隐私。但是很多时候,我们自己也是深受其害,因为不知道自己已经输入了几个字符了,这就有可能会让不自信的人删完,再重输入一遍。

同样的Python标准库里面有一个叫getpass的库,比较简单,针对于windows 和 Mac OS X都适配。用途也很广泛,但是唯一的缺点可能就跟上面说道的一样,不能显示已经输入了多少个字符! 这就显得很尴尬了。

那么今天就从易用性的角度出发,写一个更好用的getpass出来吧。


编程伊始

类比于一个进度条,在输入数据的时候,是不能够换行的。也就是说,提示语句只会在本行内显示。

常用的print函数末尾会自动的换行回车,所以我们不能用它了。然而sys.stdout.write则不会在后面添加额外的东西。二者正是我们想要的。但是其存在一个问题,那就是不强制输出的话,默认不输出信息,所以我们还需要强制输出一下。借助于sys.stdout.flush函数即可。

下面先来看个小例子,就很容易明白了。

def test():
    import sys, time

    for i in range(5):
        sys.stdout.write(str(i) * (5 - i) + '\r')
        sys.stdout.flush()
        time.sleep(1)

运行结果如下:

正式实施

根据上面的思想,稍微动动脑筋我们就可以实现想要的功能了。代码很简单,大致如下:

# coding:utf-8
import sys, os
from time import *

reload(sys)
sys.setdefaultencoding('utf8')
#    __author__ = '郭 璞'
#    __date__ = '2016/10/15'
#    __Desc__ = 改进版的getpass,更易用,更好用!

def getpass(prompt='', tip = 'You have typed %d characters!'):
    # print the prompt to prompt user what to do
    print prompt
    import msvcrt
    # get one charecter from terminal
    cur_character = msvcrt.getch()
    # the result will be out final answer!
    result =''+cur_character
    count = 1
    # 循环的读取从控制台输入的字符数据 get character once a time from terminal
    while cur_character!= '\r':
        # show message at the old line with the help of  the function named sys.stdout.write and sys.stdout.flush
        sys.stdout.write(tip%(count)+"\r")
        sys.stdout.flush()
        # update the needed item
        cur_character = msvcrt.getch()
        result += cur_character
        count += 1
    # to avoid overlap the message, we'd better go to next new line.
    print "\n"
    # return what we really need
    return result

if __name__ == '__main__':
    password = getpass(prompt='\bplease input your username(there should contains no space):')
    print password

运行结果,符合我们的需求,如下:

最后输出了输入结果的原因就是我们main函数里面故意输出了,具体怎么用取决于您的代码。

改进版

至于改进版,是添加了自定义delimiter需求,以及完善“中途删除操作”等。

源码

# coding:utf-8
import sys, os
from time import *

reload(sys)
sys.setdefaultencoding('utf8')
#    __author__ = '郭 璞'
#    __date__ = '2016/10/15'
#    __Desc__ =   just like getpass lib, this is also simple and easy to use. While the drawback is it's not so much pythonic in the implement of the function 'replace'.
#                  I am happy to hear you can join me to slove it. :)
#                 改进版的getpass,更易用,更好用! 唯一的缺点就是replace函数中的实现略显粗糙,欢迎前来完善。

# show the numbers we have typed
def showByNumbers(prompt='', tip = 'You have typed %d characters!'):
    # print the prompt to prompt user what to do
    print prompt
    import msvcrt
    # get one charecter from terminal
    cur_character = msvcrt.getch()
    # the result will be out final answer!
    result =''+cur_character
    count = 1
    # 循环的读取从控制台输入的字符数据 get character once a time from terminal
    while cur_character!= '\r':
        # show message at the old line with the help of  the function named sys.stdout.write and sys.stdout.flush
        sys.stdout.write(tip%(count)+"\r")
        sys.stdout.flush()
        # update the needed item
        cur_character = msvcrt.getch()
        if cur_character =="\b":
            result = result[0:-1]
            count -=1
        else:
            result += cur_character
            count += 1
    # to avoid overlap the message, we'd better go to next new line.
    print "\n"
    # return what we really need
    return result

# use the constom char to replace what we typed
def replaceWithDelimiter(prompt='', delimiter = '*'):
    print prompt
    import msvcrt

    current_character = msvcrt.getch()
    count = 1
    result = ''
    result += current_character

    # if we typed backspace key, we should update the interface right now!
    delta = 0

    # get a character once a time and do something if meet the backspace
    while current_character!='\r':
        # build the stars to show
        stars = ''
        for index in range(count):
            stars += delimiter
            for i in range(delta):
                stars += ' '
        sys.stdout.write(prompt + stars + "\r")
        sys.stdout.flush()

        # update for next loop
        current_character = msvcrt.getch()
        # consider the backspace key
        if current_character == '\b':
            count -=1
            result = result[0:-1]
            # for erase the extra delimiters
            delta +=1
        else:
            result += current_character
            count +=1

    # it's necessary to print in a new line for avoiding overlapping
    print "\n"
    # return what we really need
    return result

def getpass(prompt='', mode='n', tip='You have typed %d characters!', delimiter='*'):

    if mode =='n':
        return showByNumbers(prompt=prompt, tip=tip)
    elif mode == 'r':
        return replaceWithDelimiter(prompt=prompt, delimiter=delimiter)
    else:
        raise NameError('There are only two choice, so check your input!')

if __name__ == '__main__':
    """
    Here are some useful test. And you can also do it just like this!
    :)
    """
    # password = getpass(prompt='\bplease input your username(there should contains no space):')
    # print password
    # password = replaceWithDelimiter(prompt='\bplease input your username(there should contains no space):', delimiter='')
    # print password
    password = getpass(prompt='\bplease input your username(there should contains no space):', mode='n')
    print password

    pwd = getpass(prompt='\bplease input your username(there should contains no space):', mode='r', delimiter='#')
    print pwd

以数字显示

以自定义分隔符delimiter显示

如何使用?

由于博主将这个工具封装好了,而且已经上传到了pypi上面。所以大家可以很容易的下载以及安装。

下载及安装

pip install getpass2

在您的代码中使用

不出意外的话,使用下面的代码即可。

from getpass2 import getpass

......

如果,没能正常的工作,找到您的Python的site-packages,找到getpass2文件夹,将里面的getpass2.py拷贝到您的项目中即可。同样可以完美的运行。

源码下载

如果您想直接看一下源码的话,可以到博主的GitHub上直接下载。下载链接如下:

https://github.com/guoruibiao/getpass2

总结

本篇文章主要是介绍了完善Python标准库的一个小案例。其实并没有什么难于理解的地方。关键在于动手实践。

如果您对此有兴趣,不妨fork 或者star来一起完善一下吧。

(^__^) 嘻嘻……

改进版getpass库的更多相关文章

  1. 《Ansible权威指南》笔记(3)——Ad-Hoc命令集,常用模块

    五.Ad-Hoc命令集1.Ad-Hoc命令集通过/usr/bin/ansible命令实现:ansible <host-pattern> [options]    -v,--verbose  ...

  2. python学习笔记——(二)循环

    ·密文输入引入getpass库使用getpass.getpass("password:")tips:该功能在PyCharm中不好使,只能在命令行用 ·python强制缩进,省略了大 ...

  3. Python学习【02】Python基础

    一.Python内部执行过程 1.Python的后缀名可以是任意? print("hello,world")  保存成  .py / .txt / .sb / .aaa 都可以用在 ...

  4. 3rd,Python登录模拟

    需求: 1. 用户输入帐号密码进行登陆 2. 用户信息保存在文件内 3. 用户密码输入错误三次后锁定用户 #导入getpass库,用于密码验证 import getpass #定义用户名.密码 _us ...

  5. Python在七牛云平台的应用(一)

    七牛云:(引用百度的介绍)七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化PaaS服务.围绕富媒体场景,七牛先后推出了对象存储,融合CDN加速,数据通用处理,内容反垃圾服务,以及直 ...

  6. Python趣味实用小工具

    代码地址如下:http://www.demodashi.com/demo/12918.html python 趣味实用小工具 概述 用python实现的三个趣味实用小工具: 图片转Execl工具 , ...

  7. 4.1、Ansible模块

    ansible-doc -l    列出所有模块 ansible-doc 模块名    查看模块的help说明 ansible-doc -s  module_name:获取指定模块的使用信息 ***文 ...

  8. python3学习笔记一

    install 安装软件包download 下载安装包uninstall 卸载安装包freeze 按照req uirements 格式输出安装包,可以到其他服务器上执行pip install -r r ...

  9. DAY2 Python 标准库 -> Getpass 模块 -> 命令行下输入密码的方法.

    getpass 模块 getpass 模块提供了平台无关的在命令行下输入密码的方法. getpass(prompt) 会显示提示字符串, 关闭键盘的屏幕反馈, 然后读取密码. 如果提示参数省略, 那么 ...

随机推荐

  1. [Micropython]TPYBoard v10x拼插编程实验 点亮心形点阵

    一.什么是TPYBoard开发板 TPYBoard是以遵照MIT许可的MicroPython为基础,由TurnipSmart公司制作的一款MicroPython开发板,它基于STM32F405单片机, ...

  2. [LeetCode] Parse Lisp Expression 解析Lisp表达式

    You are given a string expression representing a Lisp-like expression to return the integer value of ...

  3. C++11的value category(值类别)以及move semantics(移动语义)

    转载请保留以下声明 作者:赵宗晟 出处:http://www.cnblogs.com/zhao-zongsheng/p/value_categories_and_move_semantics.html ...

  4. [LOJ 6248]「CodePlus 2017 11 月赛」晨跑

    Description “无体育,不清华”.“每天锻炼一小时,健康工作五十年,幸福生活一辈子” 在清华,体育运动绝对是同学们生活中不可或缺的一部分.为了响应学校的号召,模范好学生王队长决定坚持晨跑.不 ...

  5. [SDOI 2009]HH去散步

    Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...

  6. UVALive - 3530:Martian Mining

    dp 可以发现,对于(i,j),要么把它运上去,那么把它运到左边,枚举一下即可 #include<cstdio> #include<cstdlib> #include<a ...

  7. [BZOJ]1042 硬币购物(HAOI2008)

    失踪OJ回归. 小C通过这道题mark一下容斥一类的问题. Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买s ...

  8. C语言程序第一次作业

    (一)实验总结 1. 求圆面积和周长 (1)题目 输入圆的半径,计算圆的周长和面积. (2)流程图 (3)测试数据及运行结果 测试数据1:r=2 运行结果: (4)实验分析 没有问题 2.判断闰年 ( ...

  9. vrn:基于直接体积回归的单幅图像大姿态三维人脸重建

    3D面部重建是一个非常困难的基本计算机视觉问题.目前的系统通常假设多个面部图像(有时来自同一主题)作为输入的可用性,并且必须解决许多方法学挑战,例如在大的面部姿势,表情和不均匀照明之间建立密集的对应. ...

  10. SecureFX连接Linux后文件夹中文乱码问题解决(转)

    在使用SecureFX 连接Linux 时,发现文件夹显示乱码,一直尝试各种配置,现将方法整理一下!供大家参考! 首先在选项中设置字符编码为UTF-8 然后在全局选项中找到Securefx的配置文件 ...