【簡介】python
今天忽然想到一個事,linux-termial 下一個優秀的程序在輸入密碼的時候整個窗口是看不到密碼的明文的;我前一段時間老是用input來接收輸入的信息,linux
明顯沒有逼格啊!並且我堅信 python 中必定已經有這個輪子了。ios
【三行代碼成就有逼格的密碼輸入】sql
總的來講就是用getpass模塊的getpass函數(和input的用法同樣哈!)app
In [1]: import getpass In [2]: password = getpass.getpass("user password:") user password: In [3]: password Out[3]: '12345678'
【源碼的關鍵部分】函數
能夠看到 getpass 和 input 的低層實現都是 sys.stdin spa
def _raw_input(prompt="", stream=None, input=None): # This doesn't save the string in the GNU readline history. if not stream: stream = sys.stderr if not input: input = sys.stdin prompt = str(prompt) if prompt: try: stream.write(prompt) except UnicodeEncodeError: # Use replace error handler to get as much as possible printed. prompt = prompt.encode(stream.encoding, 'replace') prompt = prompt.decode(stream.encoding) stream.write(prompt) stream.flush() # NOTE: The Python C API calls flockfile() (and unlock) during readline. line = input.readline() if not line: raise EOFError if line[-1] == '\n': line = line[:-1] return line def unix_getpass(prompt='Password: ', stream=None): """Prompt for a password, with echo turned off. Args: prompt: Written on stream to ask for the input. Default: 'Password: ' stream: A writable file object to display the prompt. Defaults to the tty. If no tty is available defaults to sys.stderr. Returns: The seKr3t input. Raises: EOFError: If our input tty or stdin was closed. GetPassWarning: When we were unable to turn echo off on the input. Always restores terminal settings before returning. """ passwd = None with contextlib.ExitStack() as stack: try: # Always try reading and writing directly on the tty first. fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY) tty = io.FileIO(fd, 'w+') stack.enter_context(tty) input = io.TextIOWrapper(tty) stack.enter_context(input) if not stream: stream = input except OSError as e: # If that fails, see if stdin can be controlled. stack.close() try: fd = sys.stdin.fileno() except (AttributeError, ValueError): fd = None passwd = fallback_getpass(prompt, stream) input = sys.stdin if not stream: stream = sys.stderr if fd is not None: try: old = termios.tcgetattr(fd) # a copy to save new = old[:] new[3] &= ~termios.ECHO # 3 == 'lflags' tcsetattr_flags = termios.TCSAFLUSH if hasattr(termios, 'TCSASOFT'): tcsetattr_flags |= termios.TCSASOFT try: termios.tcsetattr(fd, tcsetattr_flags, new) passwd = _raw_input(prompt, stream, input=input) finally: termios.tcsetattr(fd, tcsetattr_flags, old) stream.flush() # issue7208 except termios.error: if passwd is not None: # _raw_input succeeded. The final tcsetattr failed. Reraise # instead of leaving the terminal in an unknown state. raise # We can't control the tty or stdin. Give up and use normal IO. # fallback_getpass() raises an appropriate warning. if stream is not input: # clean up unused file objects before blocking stack.close() passwd = fallback_getpass(prompt, stream) stream.write('\n') return passwd try: import termios # it's possible there is an incompatible termios from the # McMillan Installer, make sure we have a UNIX-compatible termios termios.tcgetattr, termios.tcsetattr except (ImportError, AttributeError): try: import msvcrt except ImportError: getpass = fallback_getpass else: getpass = win_getpass else: getpass = unix_getpass
----rest