常用字符编码:ASCII
GBK
Unicode(UTF-8,UTF-16,UTF-32)
str编码bytes:str.encode()
bytes解码str:bytes.decode()
编码和解码时要指定类型,例如:
# 编码
text = "Hello, 你好"
encoded_bytes = text.encode("utf-8")
# 解码
bytes_data = b'Hello, \xe4\xbd\xa0\xe5\xa5\xbd'
decoded_text = bytes_data.decode("utf-8")
open()
打开文件,指定文件路径和操作模式。close()
方法关闭文件,释放资源。read(size=-1)
:从文件中读取指定大小的内容,若不指定大小则读取全部内容。readline()
:逐行读取文件内容。readlines()
:将文件内容按行读取,并返回一个包含所有行的列表。write(string)
:将字符串写入文件。writelines(lines)
:将包含多行文本的列表写入文件。seek(offset[, whence])
:改变当前文件指针的位置,用于定位读写位置。mode 参数指的是打开文件的模式,用于指定文件的打开方式和操作类型
常见的取值:
"r"
:只读模式(默认)。以只读模式打开文件,你只能读取文件的内容,不能进行写入操作。如果文件不存在,会引发FileNotFoundError
异常。"w"
:写入模式。以写入模式打开文件,如果文件存在,则会截断(清空)文件的内容,然后你可以向文件中写入新的内容。如果文件不存在,会创建一个新文件。"a"
:追加模式。以追加模式打开文件,你可以将新的内容追加到文件的末尾,而不影响文件原有的内容。如果文件不存在,会创建一个新文件。"x"
:排他性创建模式。以排他性创建模式打开文件,只有当文件不存在时才能成功打开,否则会引发FileExistsError
异常。"b"
:二进制模式。以二进制模式打开文件,适用于处理二进制文件,如图像、音频或视频文件。在其他模式后添加"b"
表示以二进制模式打开文件,例如"rb"
表示以二进制只读模式打开文件。"t"
:文本模式(默认)。以文本模式打开文件,可以处理文本文件的内容。这是默认的模式,通常不需要显式指定。'+'
:读写模式,可同时读写文件。配置文件的格式可以使用常见的文件格式,如 INI 文件、JSON 文件、YAML 文件等。其中,INI 文件是一种常见的格式,以键值对的形式存储配置信息。
解析配置文件常用到的模块是 configparser
,其中的 ConfigParser
类提供了解析和处理配置文件的功能。
ConfigParser
类的常用方法:
read(filename)
:读取配置文件。sections()
:返回所有的配置节。options(section)
:返回指定配置节的所有选项。get(section, option)
:获取指定配置节和选项的值。json 模块中常用的四个函数:
json.loads(s)
:将 JSON 字符串解析为 Python 对象。json.dumps(obj)
:将 Python 对象序列化为 JSON 字符串。json.load(fp)
:从文件中读取 JSON 数据并解析为 Python 对象。json.dump(obj, fp)
:将 Python 对象序列化为 JSON 数据并写入文件。xmltodict 是一个用于将 XML 数据解析为 Python 字典的模块。
使用 xmltodict 处理 XML 数据的流程:
xmltodict.parse()
方法,将 XML 数据作为参数传入,得到一个 Python 字典表示的数据结构。例如,将 XML 数据解析为 Python 字典:
import xmltodict
xml_data = """
Python Programming
John Doe
"""
data_dict = xmltodict.parse(xml_data)
使用pip包管理器安装,执行如下命令:
pip install psutil
psutil 模块可以用于监控系统的各种信息,包括:
cpu_percent = psutil.cpu_percent() # 获取 CPU 使用百分比
cpu_count = psutil.cpu_count() # 获取 CPU 核心数量
cpu_stats = psutil.cpu_stats() # 获取 CPU 统计信息
memory = psutil.virtual_memory() # 获取虚拟内存使用情况
memory_percent = memory.percent # 获取内存使用百分比
memory_total = memory.total # 获取内存总量
memory_used = memory.used # 获取已使用的内存量
disk_usage = psutil.disk_usage('/') # 获取根目录磁盘使用情况
disk_percent = disk_usage.percent # 获取磁盘使用百分比
disk_total = disk_usage.total # 获取磁盘总量
disk_used = disk_usage.used # 获取已使用的磁盘量
network_stats = psutil.net_io_counters() # 获取网络统计信息
bytes_sent = network_stats.bytes_sent # 获取发送的字节数
bytes_received = network_stats.bytes_recv # 获取接收的字节数
watchdog 是一个 Python 库,用于监控文件系统的变化。
watchdog 监控指定目录/文件变化的工作原理:
Observer
对象。EventHandler
对象,继承 FileSystemEventHandler
类,重写需要处理的文件系统事件方法。EventHandler
对象注册到 Observer
对象中。Observer
对象,开始监控文件系统的变化。当目录/文件发生变化时,Observer
会通知注册的 EventHandler
对象,并调用相应的方法进行处理。
在 subprocess.Popen
类构造函数的参数中,stdin
、stdout
和 stderr
的默认取值分别是 None
,表示子进程的标准输入、标准输出和标准错误输出被重定向到 subprocess.PIPE
。
subprocess.PIPE
表示创建一个管道,可以通过管道与子进程进行输入和输出交互。
如果需要将子进程的输出传给父进程处理,可以使用 communicate()
方法,该方法会等待子进程结束并返回子进程的输出。
例如:
import subprocess
process = subprocess.Popen(["command", "arg1", "arg2"], stdout=subprocess.PIPE)
output, error = process.communicate()
print(output.decode("utf-8"))
日志的作用是记录程序运行时的关键事件和信息,方便排查问题和了解程序的运行状态。
通过日志记录事件时,通常需要记录以下方面的信息:
日志还可以包含其他信息,如线程号、模块名、函数名等,以便更好地定位和分析问题。
在 logging 模块中,日志的级别从低到高依次是:
在 logging 模块中,记录器(Logger)、处理器(Handler)和格式化器(Formatter)是三个核心概念。
记录器、处理器和格式化器之间的关系:
addHandler()
方法添加处理器。setFormatter()
方法设置格式化器。setLevel()
方法设置日志级别。例如,创建一个记录器并添加处理器:
import logging
logger = logging.getLogger("my_logger")
handler = logging.StreamHandler() # 创建一个处理器,输出日志到控制台
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") # 创建一个格式化器
handler.setFormatter(formatter) # 设置处理器的格式化器
logger.addHandler(handler) # 添加处理器到记录器
使用 pyftpdlib API 编程可以实现更丰富的功能,如:
smtplib
模块,创建 SMTP 连接。sendmail()
方法发送邮件。常用的类或方法:
smtplib.SMTP
:创建 SMTP 连接的类。SMTP.login(user, password)
:登录邮件服务器。SMTP.sendmail(from_addr, to_addrs, msg)
:发送邮件。MIMEText
:创建邮件正文的类。MIMEMultipart
:创建带附件的邮件的类。例如,发送简单文本邮件的示例代码:
import smtplib
from email.mime.text import MIMEText
# 邮件内容
msg = MIMEText("Hello, this is a test email.", "plain")
# 发件人和收件人
msg["From"] = "[email protected]"
msg["To"] = "[email protected]"
msg["Subject"] = "Test Email"
# SMTP 连接
smtp_server = smtplib.SMTP("smtp.example.com", 587)
smtp_server.starttls()
# 登录邮箱
smtp_server.login("username", "password")
# 发送邮件
smtp_server.sendmail("[email protected]", "[email protected]", msg.as_string())
# 关闭连接
smtp_server.quit()
Lock
:进程锁,用于实现进程间的互斥访问。常用的方法有 acquire()
获取锁,release()
释放锁。Event
:事件对象,用于进程间的通信和同步。常用的方法有 set()
设置事件为真,clear()
清除事件为假,wait()
等待事件被设置。Condition
:条件对象,用于实现复杂的进程同步。常用的方法有 acquire()
获取条件锁,release()
释放条件锁,wait()
等待条件,notify()
通知等待的进程,notify_all()
通知所有等待的进程。Semaphore
:信号量对象,用于控制进程的访问数量。常用的方法有 acquire()
获取信号量,release()
释放信号量。Queue
:进程安全的队列,用于进程间的数据通信。常用的方法有 put()
向队列中放入数据,get()
从队列中获取数据。Pipe
:进程间的管道,用于双向通信。常用的方法有 send()
向管道发送数据,recv()
接收管道中的数据。Lock
:线程锁,用于实现线程间的互斥访问。常用的方法有 acquire()
获取锁,release()
释放锁。Event
:事件对象,用于线程间的通信和同步。常用的方法有 set()
设置事件为真,clear()
清除事件为假,wait()
等待事件被设置。Condition
:条件对象,用于实现复杂的线程同步。常用的方法有 acquire()
获取条件锁,release()
释放条件锁,wait()
等待条件,notify()
通知等待的线程,notify_all()
通知所有等待的线程。Semaphore
:信号量对象,用于控制线程的访问数量。常用的方法有 acquire()
获取信号量,release()
释放信号量。Queue
:线程安全的队列,用于线程间的数据通信。常用的方法有
put()
向队列中放入数据
get()
从队列中获取数据。
协程是一种用户态的轻量级线程,可以在单线程中实现多任务的并发执行。协程通过自身的控制,可以在任务执行过程中主动让出CPU,以便执行其他任务,从而实现高效的并发编程。
协程适用于 I/O 密集型任务,特别是需要频繁进行网络请求、数据库操作等阻塞操作的场景。使用协程可以充分利用 CPU 时间,提高程序的并发性能。
主机清单 Inventory 文件是 Ansible 的一项重要配置,用于指定被管理的主机。
主机清单文件可以采用 INI 格式或 YAML 格式进行定义。在 INI 格式中,可以按组织结构定义主机和组,如:
[web]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
[db]
db1 ansible_host=192.168.1.20
在 YAML 格式中,可以按字典方式定义主机和组,如:
all:
hosts:
web1:
ansible_host: 192.168.1.10
web2:
ansible_host: 192.168.1.11
children:
web:
hosts:
web1:
web2:
db:
hosts:
db1:
ssh-keygen
命令生成密钥对。ssh-copy-id
命令将公钥复制到被管理的主机上,或手动将公钥内容添加到被管理主机的 ~/.ssh/authorized_keys
文件中。ssh
命令测试从控制节点到被管理主机的免密登录是否生效。Ansible ad-hoc 模式是一种临时执行命令的方式,常用于快速执行一些简单的任务。
常见的 ad-hoc 命令示例:
ansible -m -a ""
ansible -m copy -a "src= dest="
ansible -m yum -a "name= state=present"
ansible -m service -a "name= state=restarted"
YAML(YAML Ain’t Markup Language)是一种人类可读的数据序列化格式,常用于配置文件和数据交换。
YAML 使用缩进和冒号来表示层级关系,支持列表、字典和基本数据类型。
示例:
web:
- host: web1
ip: 192.168.1.10
- host: web2
ip: 192.168.1.11
db:
- host: db1
ip: 192.168.1.20
Ansible playbook 是用于定义和执行多个任务的配置文件。
一个简单的 playbook 示例:
- name: Install and start Nginx
hosts: web
tasks:
- name: Install Nginx
yum:
name: nginx
state: present
- name: Start Nginx service
service:
name: nginx
state: started
APScheduler 是一个用于在 Python 应用中执行定时任务的库。它提供了灵活的调度方式,支持多种调度器(Scheduler)和触发器(Trigger),可以执行定时任务、周期性任务和延迟任务。APScheduler 可以与各种 Python 框架和应用程序集成,帮助开发者方便地实现定时任务调度功能。
Paramiko 是一个用于在 Python 中执行远程命令和传输文件的模块。它实现了 SSH2 协议,可以通过 SSH 连接远程服务器,并执行命令、上传下载文件。Paramiko 提供了高级的 SSH 客户端接口,支持远程命令执行、SFTP 文件传输和 SSH 通道的建立。它可以在 Python 程序中实现远程服务器的管理和操作。
Celery 通过使用任务队列来实现任务的分发和执行,可以配置多个队列,并根据任务的类型或其他条件将任务分配到不同的队列中。
在 Celery 的配置文件中,可以通过 CELERY_QUEUES
参数定义多个队列,并为每个队列指定名称、路由规则和优先级。
示例配置:
CELERY_QUEUES = (
Queue('default', routing_key='default'),
Queue('tasks', routing_key='tasks'),
)
CELERY_ROUTES = {
'myapp.tasks.default_task': {'queue': 'default', 'routing_key': 'default'},
'myapp.tasks.task1': {'queue': 'tasks', 'routing_key': 'tasks'},
}
上述配置定义了两个队列:default
和 tasks
,并分别指定了路由规则。根据任务的函数名称,可以将任务分配到相应的队列中。例如,default_task
函数的任务会被分配到 default
队列,task1
函数的任务会被分配到 tasks
队列。通过这种方式,可以实现不同队列执行不同的任务。
在 Python 中进行进程同步编程,可以使用多种方法,包括锁、条件变量、信号量等。下面介绍一些常用的进程同步方法:
锁(Lock):
锁是一种最基本的同步机制,用于确保在任何给定时间只有一个进程可以访问共享资源。Python 提供了 multiprocessing
模块中的 Lock
类来实现锁机制。
from multiprocessing import Process, Lock
def worker(lock, data):
lock.acquire()
try:
# 访问共享资源的代码
print("Worker:", data)
finally:
lock.release()
if __name__ == '__main__':
lock = Lock()
processes = []
for i in range(5):
p = Process(target=worker, args=(lock, i))
processes.append(p)
p.start()
for p in processes:
p.join()
Event
是一种简单的同步原语,可以用于线程或进程之间的事件通知。
下面是使用 Event
实现进程同步通信的示例:
from multiprocessing import Process, Event
def worker(event, data):
event.wait() # 等待事件触发
print("Worker:", data)
if __name__ == '__main__':
event = Event()
processes = []
for i in range(5):
p = Process(target=worker, args=(event, i))
processes.append(p)
p.start()
# 触发事件,通知所有进程可以开始工作
event.set()
for p in processes:
p.join()
条件变量(Condition):
条件变量用于在多个进程之间实现复杂的同步和通信。Python 中的 multiprocessing
模块提供了 Condition
类来实现条件变量。
from multiprocessing import Process, Condition
def producer(condition):
with condition:
print("Producer: Producing item...")
# 生产项目的代码
condition.notify() # 通知消费者
condition.wait() # 等待消费者消费
def consumer(condition):
with condition:
condition.wait() # 等待生产者生产
print("Consumer: Consuming item...")
# 消费项目的代码
condition.notify() # 通知生产者
if __name__ == '__main__':
condition = Condition()
p1 = Process(target=producer, args=(condition,))
p2 = Process(target=consumer, args=(condition,))
p1.start()
p2.start()
p1.join()
p2.join()
信号量(Semaphore):
信号量用于控制对共享资源的访问数量。Python 的 multiprocessing
模块提供了 Semaphore
类来实现信号量。
from multiprocessing import Process, Semaphore
def worker(semaphore, data):
semaphore.acquire()
try:
# 访问共享资源的代码
print("Worker:", data)
finally:
semaphore.release()
if __name__ == '__main__':
semaphore = Semaphore(2) # 设置允许的进程数
processes = []
for i in range(5):
p = Process(target=worker, args=(semaphore, i))
processes.append(p)
p.start()
for p in processes:
p.join()
这些是在 Python 中进行进程同步编程的一些常用方法。根据具体情况选择适合的同步机制,并使用适当的同步原语来保护共享资源的访问。
下面是一个示例 Playbook,演示了如何进行用户管理、文件管理以及 LNMP(Linux + Nginx + MySQL + PHP)的安装和配置等方面操作:
---
- name: Network Operations Final Exam
hosts: web_servers
become: true
tasks:
- name: Create user
user:
name: john
password: "{{ 'password' | password_hash('sha512') }}"
state: present
- name: Copy SSH public key
authorized_key:
user: john
key: "{{ lookup('file', '/path/to/public_key.pub') }}"
- name: Ensure Nginx is installed
apt:
name: nginx
state: present
- name: Copy Nginx configuration file
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: restart nginx
- name: Install MySQL and PHP packages
apt:
name: "{{ item }}"
state: present
with_items:
- mysql-server
- php-fpm
- php-mysql
- name: Configure MySQL root password
debconf:
name: mysql-server
question: 'mysql-server/root_password'
value: 'root_password'
vtype: password
- name: Copy PHP configuration file
template:
src: php.ini.j2
dest: /etc/php/7.4/fpm/php.ini
owner: root
group: root
mode: '0644'
- name: Start and enable Nginx service
service:
name: nginx
state: started
enabled: true
- name: Start and enable PHP-FPM service
service:
name: php7.4-fpm
state: started
enabled: true
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
编写 Ansible Playbook 可以遵循以下步骤:
创建一个新的 YAML 文件,例如 playbook.yml
。
在文件中定义 Playbook 的基本结构,包括主机、远程用户、变量等信息。
---
- name: My Playbook
hosts: web_servers
remote_user: ansible
become: true
vars:
var1: value1
var2: value2
name
是 Playbook 的名称,可以任意取名。hosts
定义了 Playbook 执行的目标主机或主机组。remote_user
是用于远程连接的用户名。become: true
表示在执行任务时切换为超级用户(例如 sudo
)。在 Playbook 中添加任务(tasks)。每个任务都是一个操作单元,用于在目标主机上执行特定的操作。
---
- name: My Playbook
hosts: web_servers
remote_user: ansible
become: true
vars:
var1: value1
var2: value2
tasks:
- name: Task 1
<module_name>:
<module_arguments>
- name: Task 2
<module_name>:
<module_arguments>
name
是任务的名称,可以任意取名。
是要执行的 Ansible 模块的名称,例如 apt
、copy
、service
等。
是模块的参数,用于指定模块的具体行为。可以根据需要为任务添加条件、循环、变量等其他功能。这些功能可以通过 Ansible 提供的模块和语法来实现。
---
- name: My Playbook
hosts: web_servers
remote_user: ansible
become: true
vars:
var1: value1
var2: value2
tasks:
- name: Task 1
<module_name>:
<module_arguments>
when: <condition>
- name: Task 2
<module_name>:
<module_arguments>
loop: "{{ items }}"
vars:
var3: "{{ item }}"
when
关键字用于指定任务执行的条件。只有满足条件时,任务才会执行。loop
关键字用于指定循环的迭代器。vars
关键字用于定义任务级别的变量。保存并运行 Playbook。
ansible-playbook playbook.yml
在运行 Playbook 时,Ansible 会连接到目标主机并执行每个任务。你可以在终端中查看执行结果,并根据需要进行调试和修改。