在运行的时候提供密码输入提示
我们已经编写好了一个脚本,其中需要用户输入密码。但是由于脚本是用来做交互式使用的,我们想为用户提供密码输入提示。在这种情况下,Python的getpass模块就可以巧妙地解决这个问题。比如这样:
import getpass
user = getpass.getuser()
passwd = getpass.getpass()
if svc_login(user, passwd): # You must write svc_login()
print('Yay!')
else:
print('Boo!')
注意,在上面的代码中,getpass.getuser()并不会提示用户输入用户名。相反,他会自动根据用户的shell环境使用当前的用户登录名,或者是以本地系统的密码数据库为支撑。
如果你想更加可靠,想显示给用户提供用户名输入,那么我们可以使用内置的input函数:
user = input('Enter your username:')
同样你需要记得的是,在有些系统上可能不支持将输入给getpass()方法的密码做隐藏处理。在这种情况下,Python会尽可能的发出预警信息来让用户及时处理。
获取终端大小
我们需要获取终端的大小,以此来对程序输出做适当对格式化处理。对于这种情况,我们可以采用os.get_terminal_size()函数来完成:
>>> import os
>>> sz = os.get_terminal_size()
>>> sz
os.terminal_size(columns=80, lines=24)
>>> sz.columns
80
>>> sz.lines
24
>>>
执行外部命令并获取输出
我们想执行一个外部命令并把输出保存为一个Python字符串。对于这种情况,我们可以使用函数subprocess.check_output()来完成:
import subprocess
out_bytes = subprocess.check_output(['netstat','-a'])
这段代码执行一个指定的命令并将执行结果以一个字节字符串的形式返回。 如果你需要文本形式返回,加一个解码步骤即可。例如:
out_text = out_bytes.decode('utf-8')
如果被执行的命令以非零码返回,就会抛出异常。 下面的例子捕获到错误并获取返回码:
try:
out_bytes = subprocess.check_output(['cmd','arg1','arg2'])
except subprocess.CalledProcessError as e:
out_bytes = e.output # Output generated before error
code = e.returncode # Return code
通常来讲,命令的执行不需要使用到底层shell环境(比如sh、bash)。 一个字符串列表会被传递给一个低级系统命令,比如os.execve()。 如果你想让命令被一个shell执行,传递一个字符串参数,并设置参数shell=True. 有时候你想要Python去执行一个复杂的shell命令的时候这个就很有用了,比如管道流、I/O重定向和其他特性。例如:
out_bytes = subprocess.check_output('grep python | wc > out', shell=True)
需要注意的是在shell中执行命令会存在一定的安全风险,特别是当参数来自于用户输入时。 这时候可以使用 shlex.quote() 函数来将参数正确的用双引用引起来。
使用check_output()函数是执行外部命令并获取其返回值的最简单方式。 但是,如果你需要对子进程做更复杂的交互,比如给它发送输入,你得采用另外一种方法。 这时候可直接使用subprocess.Popen类。例如:
import subprocess
# Some text to send
text = b'''hello worldthis is a testgoodbye'''
# Launch a command with pipes
p = subprocess.Popen(['wc'],
stdout = subprocess.PIPE,
stdin = subprocess.PIPE)
# Send the data and get the output
stdout, stderr = p.communicate(text)
# To interpret as text, decode
out = stdout.decode('utf-8')
err = stderr.decode('utf-8')
subprocess 模块对于依赖TTY的外部命令不合适用。 例如,你不能使用它来自动化一个用户输入密码的任务(比如一个ssh会话)。 这时候,你需要使用到第三方模块了,比如基于著名的 expect家族的工具(pexpect或类似的。
参考书目:
《Python CookBook》作者:【美】 David Beazley, Brian K. Jones