改良版getpassライブラリ
12780 ワード
Linuxを使用したことがあることはよく知られていますが、特にパッケージ管理ソフトウェアを使用するのはapt-getのようなもので、パスワードは表示されません.私たちのパスワードは隣の人に見られず、プライバシーを守ることができます.しかし、多くの場合、私たち自身も被害を受けています.自分が何文字を入力したか分からないので、自信のない人を削除して、もう一度入力する可能性があります.
同じPython標準ライブラリにはgetpassというライブラリがあり、windowsやMac OS Xに適しています.用途も広いですが、唯一の欠点は上記のように、何文字入力したかを表示できないかもしれません.これは気まずいように見えます.
では今日は使いやすさの観点から、より使いやすいgetpassを書いてみましょう.
プログラミングの開始
クラスは1つの進捗バーに比べて、データを入力するときは改行できません.つまり、プロンプト文はロー内にのみ表示されます.
よく使われる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 "
"
# 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 "
"
# 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 "
"
# 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を見つけて、getpass 2フォルダを見つけて、中のgetpass 2.pyをプロジェクトにコピーすればいいです.同じように完璧に運行できます.
ソースのダウンロード
ソースコードを直接見たいなら、ブロガーのGitHubで直接ダウンロードできます.ダウンロードリンクは次のとおりです.
https://github.com/guoruibiao/getpass2
まとめ
この記事では、Pythonの標準ライブラリを充実させるための小さなケースを紹介します.実は何も理解しにくいところはありません.肝心なのは実践に着手することだ.
興味があれば、forkやstarで一緒に改善してみてはいかがでしょうか.
(^^^)ヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒヒ…