2013-10-29 14 views
5

Tiếp theo đang nhắc nhở cho người dùng và mật khẩu, khi chạy trong giao diện điều khiển:Python nhắc cho người dùng với tiếng vang và mật khẩu mà không vang

import getpass 

user = getpass.getpass("Username:") 
passwd = getpass.getpass("Password for " + user + ":") 

print "Got", user, passwd 

Các vấn đề rõ ràng với trên là, tên người dùng không được lặp lại khi nó được gõ.

Bây giờ getpass documentation nói "Trên Unix, nó mặc định sử dụng/dev/tty trước khi quay trở lại sys.stdin và sys.stderr."

Câu hỏi: Cách yêu cầu cả tên người dùng và mật khẩu, để chúng được đọc từ cùng một nguồn và tên người dùng được lặp lại bình thường, trong khi mật khẩu thì không?

Trả lời

9

Tại sao không chỉ cần sử dụng raw_input cho username:

import getpass 

user = raw_input("Username:") 
passwd = getpass.getpass("Password for " + user + ":") 

print("Got", user, passwd) 

Demo:

Username:iCodez 
Password for iCodez: 
('Got', 'iCodez', 'secret') 
+0

Tôi nghĩ rằng điều này có thể không trả lời đúng câu hỏi. Như được viết trong câu hỏi, tài liệu của 'getpass' nói *" Trên Unix nó mặc định sử dụng/dev/tty trước khi quay trở lại sys.stdin và sys.stderr "*. Bạn sẽ thấy sự khác biệt của 'raw_input' và' getpass' khi bạn đang thực hiện chương trình của bạn như thế này trên linux: './my_program.py JojOatXGME

8

Sử dụng raw_input thay vì getpass.getpass cho tên người dùng.

user = raw_input("Username:") 
1

thử điều này:

user = raw_input("Username:") 
3

Nó sẽ có thể sử dụng raw_input (input trong Python 3) nhưng như đã đề cập trong câu hỏi, getpass đang sử dụng/dev/tty trước khi quay trở lại sys.stdin và sys.stderr. Điều này có nghĩa là trong một số trường hợp, getpassraw_input đang sử dụng các nguồn khác nhau.

Trên Linux, bạn có thể thấy sự khác biệt bằng cách thực hiện các ứng dụng với các lệnh sau:

my_app.py < /path/to/some/file 

Chức năng raw_input sẽ đọc từ tập tin trong khi getpass vẫn sẽ sử dụng thiết bị đầu cuối. Ngay cả khi nó không được ghi lại một cách rõ ràng, điều tương tự cũng xảy ra trên Windows.


Tôi chưa tìm thấy chức năng đang hoạt động như getpass mà không ẩn đầu vào. Tôi nghĩ bạn phải tự mình thực hiện hoặc tìm kiếm một thư viện đang thực hiện nó. Bạn có thể xem triển khai hiện tại của getpassin Python 3in Python 2.7 để lấy cảm hứng.

Tôi đã viết một ví dụ bên dưới. Về cơ bản, tôi đã sử dụng việc triển khai Python 3 và loại bỏ mọi thứ liên quan đến việc ẩn đầu vào. Sau đó, tôi đã thực hiện một số thay đổi để hỗ trợ Python 2.

def _raw_input(prompt, fin, fout): 
    if prompt: 
     try: 
      fout.write(prompt) 
     except UnicodeEncodeError: 
      # Replace characters that are not supported by the terminal 
      prompt = prompt.encode(fout.encoding, 'replace') 
      prompt = prompt.decode(fout.encoding) 
      fout.write(prompt) 
     fout.flush() 

    line = fin.readline() 
    return line[:-1] if line[-1] == '\n' else line 

def _ttyinput_unix(prompt): 
    try: 
     fd = os.open("/dev/tty", os.O_RDWR, os.O_NOCTTY) 
     if sys.version_info < (3, 0): 
      with os.fdopen(fd, 'w+', 1) as tty: 
       return _raw_input(prompt, tty, tty) 
     with io.FileIO(fd, 'w+') as tty: 
      with io.TextIOWrapper(tty) as wrapper: 
       return _raw_input(prompt, wrapper, wrapper) 
    except (OSError, AttributeError) as e: 
     return _raw_input(prompt, sys.stdin, sys.stderr) 

def _ttyinput_win(prompt): 
    if sys.stdin is not sys.__stdin__: 
     # I don't know why getpass is doing this. 
     return _raw_input(prompt, sys.stdin, sys.stderr) 

    if sys.version_info >= (3, 0): 
     getch = msvcrt.getwch 
     putch = msvcrt.putwch 
    else: 
     getch = msvcrt.getch 
     putch = msvcrt.putch 

    for c in prompt: 
     putch(c) 

    password = "" 
    while True: 
     c = getch() 
     if c == '\r' or c == '\n': 
      break 
     if c == '\003': 
      raise KeyboardInterrupt 
     if c == '\b': 
      if len(password) > 0: 
       password = password[:-1] 
       for x in "\b \b": 
        putch(x) 
     else: 
      password += c 
      putch(c) 
    putch('\r') 
    putch('\n') 

    return password 

try: 
    import msvcrt 
    ttyinput = _ttyinput_win 
except ImportError: 
    ttyinput = _ttyinput_unix 

Tôi đã thử nghiệm triển khai bằng Python 2.7 trên Windows và Python 2.7 và 3.5 trên Arch Linux.

1

Có một giải pháp thay thế khác mà tôi đã tìm thấy tài liệu here. Phát hiện xem luồng đầu vào có phải là TTY hay không và thay đổi phương thức nhập của bạn dựa trên thông tin đó.

tôi đã sử dụng một cái gì đó như thế này:

#!/usr/bin/python 

import sys 
import getpass 

if sys.stdin.isatty(): 
    print "Enter credentials" 
    username = raw_input("Username: ") 
    password = getpass.getpass("Password: ") 
else: 
    username = sys.stdin.readline().rstrip() 
    password = sys.stdin.readline().rstrip() 

print "Username: [%s], password [%s]" % (username, password) 

này hoạt động tốt từ một thiết bị đầu cuối:

bash> ./mytest.py 
Enter credentials 
Username: one 
Password: 
Username: [one], password [two] 

cho đầu vào đường ống:

bash> echo "one 
> two" | ./mytest.py 
Username: [one], password [two] 

cho đầu vào từ một tập tin:

bash> echo "one" > input 
bash> echo "two" >> input 
bash> ./mytest.py < input 
Username: [one], password [two] 

và cũng cho một heredoc:

bash> ./mytest.py << EOF 
> one 
> two 
> EOF 
Username: [one], password [two] 

Cá nhân, bao gồm tất cả các nhu cầu của tôi.

Các vấn đề liên quan