18.4. 自动化常规管理活动

学习大纲:

  • 通过重定向(redirection)、管道(pipe)和文件3种方式接收输入。

  • 在运行时处理密码。

  • 执行外部命令并获取其输出。

  • 在运行时提示输入密码,并验证密码。

  • 读取配置文件。

  • 向脚本添加日志记录和警告代码。

  • 限制CPU和内存的使用量。

  • 启动Web浏览器。

  • 使用os 模块处理目录和文件。

  • 进行备份(使用rsync )。

18.4.1. 1. 通过重定向(redirection)、管道(pipe)和文件3种方式接收输入

1.1 通过重定向接收输入

redirection.py

import sys


class Redirection(object):
    def __init__(self, in_obj, out_obj):
        self.input = in_obj
        self.output = out_obj

    def read_line(self):
        res = self.input.readline()
        self.output.write(res)
        return res


if __name__ == '__main__':
    if not sys.stdin.isatty():
        sys.stdin = Redirection(in_obj=sys.stdin, out_obj=sys.stdout)
        a = input('Enter a string: ')
        b = input('Enter another string: ')
        print('Entered strings are: ', repr(a), 'and', repr(b))

1.2 通过管道接收输入

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys

for n in sys.stdin:
    print(int(n.strip()) // 2)
$ echo 15 | python accecp.py
7
$ echo -e "10\n20\n30"|python accecp.py
5
10
15

1.3 通过文件接收输入

accept_by_input_file.py

i = open('sample.txt','r')
o = open('sample_output.txt','w')
a = i.read()
o.write(a)

18.4.2. 2. 在运行时处理密码

paramiko 模块是SSH 的Python实现,提供客户端—服务器功能。

pip3 install paramiko
import sys
import paramiko
import time

ip_address = "192.168.2.106"
username = "student"
password = "training"


ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.load_system_host_keys()
ssh_client.connect(hostname=ip_address,username=username, password=password)
print("Successful connection", ip_address)


ssh_client.invoke_shell()
remote_connection = ssh_client.exec_command('cd Desktop; mkdir work\n')
remote_connection = ssh_client.exec_command('mkdir test_folder\n')
#print( remote_connection.read() )
ssh_client.close
python3 handling_password.py

18.4.3. 3. 执行外部命令并获取其输出

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import subprocess
subprocess.call(["touch", "sample.txt"])
subprocess.call(["ls"])
print("Sample file created")
subprocess.call(["rm", "sample.txt"])
subprocess.call(["ls"])
print("Sample file deleted")

18.4.4. 4. 使用subprocess模块捕获输出

capture_output.py

import subprocess

res = subprocess.run(['ls', '-1'], stdout=subprocess.PIPE,)
print('returncode:', res.returncode)
print(' {} bytes in stdout:\n{}'.format(len(res.stdout), res.stdout.decode('utf-8')))

18.4.5. 5.在运行时提示输入密码,并验证密码

getpass 模块处理密码。Python中的getpass() 函数用于提示用户输入密码。当程序通过终端与用户交互时,getpass 模块可以用于处理密码提示

#!/usr/bin/env python
import getpass

try:
    p = getpass.getpass("Enter your password: ")
except Exception as e:
    print("Error", e)

else:
    print("Password enterd", p)

对密码进行判断,然后给予提示信息

import getpass

user_name = getpass.getuser()
print("User Name : %s" % user_name)

while True:
    passwd = getpass.getpass("Enter your Password : ")
    if passwd == '#pythonworld':
        print("Welcome!!!")
        break
    else:
        print("The password you entered is incorrect.")

18.4.6. 6.读取配置文件

read_simple.ini

[bug_tracker]
url = https://baidu.com

read_config_file.py

#!/usr/bin/env python
from configparser import ConfigParser

p = ConfigParser()
p.read('read_simple.ini')
print(p.get('bug_tracker', 'url'))

read_many_config_file.py

from configparser import ConfigParser

import glob

p = ConfigParser()
files = ['hello.ini', 'bye.ini', 'read_simple.ini', 'welcome.ini']

# read() 方法可以用于接收多个文件。它会检测每个文件,只要该文件存在,就会打开该文件并读取内容。
files_found = p.read(files)

files_missing = set(files) - set(files_found)

print('Files found:  ', sorted(files_found))
print('Files missing:  ', sorted(files_missing))

18.4.7. 7.向脚本添加日志记录和警告代码

一个简单的日志记录的示例程序。创建一个名为logging_example.py 的脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging

LOG_FILENAME = 'log.txt'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, )
logging.debug('This message should go to the log file')

with open(LOG_FILENAME, 'rt') as f:
    prg = f.read()
    print(prg)

logging_warnings_codes.py

import logging

import warnings

logging.basicConfig(level=logging.INFO, )

warnings.warn('This warning is not sent to the logs')

logging.captureWarnings(True)

warnings.warn('This warning is sent to the logs')

生成警告

generate_warnings.py

warn() 传递了一条警告消息。程序中还使用了一个简单的过滤器,它可以将警告视为错误,以提示我们根据情况解决。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import warnings

warnings.simplefilter('error', UserWarning)
print('Before')

warnings.warn('Write your warning message here')
print('After')

18.4.8. 8.限制CPU和内存的使用量

put_cpu_limit.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import resource
import sys
import signal
import time


def time_expired(n, stack):
    print('EXPIRED :', time.ctime())
    raise SystemExit('(time ran out)')


signal.signal(signal.SIGXCPU, time_expired)
# 调整CPU时间限制
soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
print('Soft limit starts as  :', soft)

resource.setrlimit(resource.RLIMIT_CPU, (10, hard))
soft, hard = resource.getrlimit(resource.RLIMIT_CPU)
print('Soft limit changed to :', soft)
print()

# 在无意义的练习中消耗一些CPU时间


print('Starting:', time.ctime())

for i in range(200000):
    for i in range(200000):
        v = i * i

print('Exiting :', time.ctime())

18.4.9. 9.启动网页浏览器

import webbrowser
webbrowser.open('https://baidu.com')

通过命令行使用Python的webbrowser 模块,命令行模式也支持所有功能。

python3 -m webbrowser -n https://www.google.com/
-n :打开新窗口。
-t :打开新标签页

18.4.10. 10.使用os模块处理目录和文件

10.1 创建目录与删除目录

os_dir_example.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os

directory_name = "abcd"
print("create directory", directory_name)

if not os.path.exists(directory_name):
    os.makedirs(directory_name)

file_name = os.path.join(directory_name, "sample_example.txt")
print("create file", file_name)

with open(file_name, 'wt') as f:
    f.write("sample example file")

print("Cleaning up")

os.unlink(file_name)  # 删除文件

os.rmdir(directory_name)  # 刪除目录

使用mkdir() 创建目录时,其父目录必须已存在。

如果使用makedirs() 创建目录,则它会创建所有目录,包括不存在的父目录。

unlink() 用于删除文件,rmdir() 用于删除目录。

10.2 检测文件系统的内容

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys

print(sorted(os.listdir(sys.argv[1])))

利用listdir() 函数可以列出指定目录中的所有内容。

18.4.11. 11. 进行备份(使用rsync)

rsync 命令用于在本地或远程复制文件和目录,rsync 也可用于数据备份。现在我们创建一个名为take_backup.py 的脚本

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import shutil
import time

from sh import rsync

con_exit = ""

def check_dir(os_dir):
    if not os.path.exists(os_dir):
        print("{} does exists".format(os_dir))
        exit(1)


def ask_for_confim():
    ans = input("Do you want to continue? yes/no\n")
    global con_exit
    if ans == "yes" or ans == "y":
        con_exit = 0
        return con_exit
    elif ans == "no" or ans == "n":
        con_exit = 1
        return con_exit
    else:
        print("Answer with yes or no")
        ask_for_confim()


def delete_fles(ending):
    for r, d, f in os.walk(backup_dir):
        for files in f:
            if files.endswith("." + ending):
                os.remove(os.path.join(r, files))


backup_dir = input("Enter directory to backup\n")
check_dir(backup_dir)
print(backup_dir, "saved.")
time.sleep(3)

backup_to_dir = input("Where to backup?\n")
check_dir(backup_to_dir)

print("Doing the backup now!")
ask_for_confim()

if con_exit == 1:
    print("Aborting the backup process!")
    exit(1)

rsync("-auhv", "--delete", "--exclude=lost+found", "--exclude=/sys", "—exclude=/tmp", "--exclude=/proc",
      "--exclude=/mnt", "--exclude=/dev", "--exclude=/backup", backup_dir, backup_to_dir)

rsync 命令也可以结合一些选项使用,如下所示。

  • -a: 存档。

  • -u: 更新。

  • -h: 显示帮助信息。

  • -v: 详细情况。

  • --delete: 从接收方删除无关文件。

  • --exclude: 排除规则。

18.4.12. 总结

我们学习了如何将常规管理任务自动化,通过各种方法接收输入、在运行时提示输入密码、执行外部命令、读取配置文件、在脚本中添加警告、通过脚本以及命令行使用webbrowser模块 、使用os 模块处理文件和目录,并进行备份。