0%

Mosh的Python课程笔记(9)--Python Standard Library

Mosh的课程网址

Files

Paths

Demo 1: Basic Methods

1
2
3
4
5
6
7
8
9
10
from pathlib import Path

path = Path(r"ecommerce/__init__.py") # create a path object
print(path.exists()) # file exists or not
print(path.is_file()) # is a file or not
print(path.is_dir()) # is a directory or not
print(path.name)
print(path.stem) # return the file name without extension
print(path.suffix) # return the extension
print(path.parent) # parent folder

输出结果:

True
True
False
__init__.py
__init__
.py
ecommerce

Demo 2

1
2
3
4
5
6
7
8
9
10
11
from pathlib import Path

path = Path(r"ecommerce/__init__.py") # create a path object

path = path.with_name("file.txt") # 产生一个新path object,(文件尚未产生)
print(path)

print(path.absolute())

path = path.with_suffix(".txt") # 产生一个新path object,(文件尚未产生)
print(path)

输出:

ecommerce\file.txt
e:\Stone\Python\HelloWorld\ecommerce\file.txt
ecommerce\file.txt

Working with Directories

Demo 1: Basic Methods

1
2
3
4
5
6
7
from pathlib import Path

path = Path("ecommerce")
path.exists()
path.mkdir() # creat this directory
path.rmdir() # remove this directory
path.rename("ecommerce2") # rename

Demo 2

1
2
3
4
from pathlib import Path

path = Path("ecommerce")
print(path.iterdir())

输出:

<generator object Path.iterdir at 0x00000180577926D0>

可见,得到的是一个generator object。因为目录下可能有大量文件,generator 更高效。

1
2
paths = [p for p in path.iterdir()]
print(paths)

输出:

[WindowsPath(‘ecommerce/customer’), WindowsPath(‘ecommerce/shopping’), WindowsPath(‘ecommerce/__init__.py’), WindowsPath(‘ecommerce/__pycache__‘)]

1
2
3
# filter: 只获取目录
paths = [p for p in path.iterdir() if p.is_dir()]
print(paths)

输出:

[WindowsPath(‘ecommerce/customer’), WindowsPath(‘ecommerce/shopping’), WindowsPath(‘ecommerce/__pycache__‘)]

1
2
3
# 当前目录下符合条件的文件
py_files = [p for p in path.glob("*.py")]
print(py_files)

输出:

[WindowsPath(‘ecommerce/__init__.py’)]

1
2
3
# recursively (包括子目录下符合条件的文件)
py_files = [p for p in path.rglob("*.py")]
print(py_files)

输出:

[WindowsPath(‘ecommerce/__init__.py’), WindowsPath(‘ecommerce/customer/contact.py’), WindowsPath(‘ecommerce/customer/__init__.py’), WindowsPath(‘ecommerce/shopping/sales.py’), WindowsPath(‘ecommerce/shopping/__init__.py’)]

Working with Files

Demo 1

1
2
3
4
5
6
from pathlib import Path

path = Path("ecommerce/__init__.py")
path.exists()
path.rename("init.txt")
path.unlink() # delete the file

Demo 2: 查看文件状态

1
2
3
from pathlib import Path

print(path.stat())

输出:

os.stat_result(st_mode=33206, st_ino=1688849860483389, st_dev=971387, st_nlink=1, st_uid=0, st_gid=0, st_size=32, st_atime=1620876102, st_mtime=1620816590, st_ctime=1620814908)

将时间转为容易识别的形式:

1
2
3
from time import ctime

print(ctime(path.stat().st_ctime)) # 打印文件的新建时间

输出:

Wed May 12 18:21:48 2021

Demo 3

1
2
3
4
print(path.read_bytes())
print(path.read_text())
path.write_bytes("...")
path.write_text("...")

输出:

b’print(“Ecommerce initialized”)\r\n’
print(“Ecommerce initialized”)

Demo 4:拷贝文件

1
2
3
4
5
6
7
8
from pathlib import Path
import shutil

source = Path("ecommerce/__init__.py")
target = Path() / "__init__.py"

# target.write_text(source.read_text()) # 简单粗暴:读->写
shutil.copy(source, target)

Working with Zip Files

Demo 1

1
2
3
4
5
6
7
from pathlib import Path
from zipfile import ZipFile

zip = ZipFile("files.zip", "w") # 生成一个zip文件
for path in Path("ecommerce").rglob("*.*"):
zip.write(path) # 将这些文件存到zip文件中
zip.close() # 关闭

Simpler way

1
2
3
4
5
6
from pathlib import Path
from zipfile import ZipFile

with ZipFile("files.zip", "w") as zip:
for path in Path("ecommerce").rglob("*.*"):
zip.write(path)

不需要手动close释放。

Demo 2

1
2
3
4
5
6
7
8
9
from pathlib import Path
from zipfile import ZipFile

with ZipFile("files.zip") as zip:
# print(zip.namelist()) # zip中的文件列表
info = zip.getinfo("ecommerce/__init__.py") # 获取文件信息
print(info.file_size) # 文件大小
print(info.compress_size) # 压缩大小
zip.extractall("extract") # 解压到extract文件夹

Working with CSV Files

Demo 1: 写csv

1
2
3
4
5
6
7
import csv

with open("data.csv", "w", newline='') as file:
writer = csv.writer(file)
writer.writerow(["transaction_id", "product_id", "price"])
writer.writerow([1000, 1, 5])
writer.writerow([1001, 2, 15])

如果不加newline=’’,文件会多空行

Demo 2: 读csv

1
2
3
4
5
import csv

with open("data.csv") as file:
reader = csv.reader(file)
print(list(reader))

输出:

[[‘transaction_id’, ‘product_id’, ‘price’], [‘1000’, ‘1’, ‘5’], [‘1001’, ‘2’, ‘15’]]

1
2
3
4
5
6
import csv

with open("data.csv") as file:
reader = csv.reader(file)
for row in reader: # reader is iterable
print(row)

输出:

[‘transaction_id’, ‘product_id’, ‘price’]
[‘1000’, ‘1’, ‘5’]
[‘1001’, ‘2’, ‘15’]

Working with JSON Files

Demo 1: write JSON files

1
2
3
4
5
6
7
8
9
10
import json
from pathlib import Path

movies = [
{"id": 1, "title": "Terminator", "year": 1989},
{"id": 2, "title": "Kindergarten Cop", "year": 1993},
]

data = json.dumps(movies)
Path("movies.json").write_text(data)

Demo 2: read JSON Files

1
2
3
4
5
6
import json
from pathlib import Path

data = Path("movies.json").read_text()
movies = json.loads(data)
print(movies[0])

输出:

{‘id’: 1, ‘title’: ‘Terminator’, ‘year’: 1989}

Working with a SQLite Database

Demo 1: write

1
2
3
4
5
6
7
8
9
10
11
import sqlite3
import json
from pathlib import Path

movies = json.loads(Path("movies.json").read_text())

with sqlite3.connect("db.sqlite3") as conn:
command = "INSERT INTO Movies VALUES(?, ?, ?)"
for movie in movies:
conn.execute(command, tuple(movie.values()))
conn.commit()

Demo 2: read

1
2
3
4
5
6
7
import sqlite3

with sqlite3.connect("db.sqlite3") as conn:
command = "SELECT * FROM Movies"
cursor = conn.execute(command)
for row in cursor:
print(row)

或:

1
2
3
4
5
6
7
import sqlite3

with sqlite3.connect("db.sqlite3") as conn:
command = "SELECT * FROM Movies"
cursor = conn.execute(command)
movies = cursor.fetchall()
print(movies)

Time

Working with Timestamps

1
2
3
4
5
6
7
8
9
10
11
12
13
import time


def send_emails():
for i in range(1000000):
pass


start = time.time()
send_emails()
end = time.time()
duration = end - start
print(duration)

输出:

0.016989707946777344

Working with DateTimes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from datetime import datetime
import time

dt1 = datetime(2018, 1, 1)
print(dt1) # 2018-01-01 00:00:00
dt2 = datetime.now()
print(dt2) # 2021-05-13 16:51:52.269074
print(dt2 > dt1) # True

dt = datetime.strptime("2018/01/01", "%Y/%m/%d") # 指定时间
print(dt) # 2018-01-01 00:00:00

dt = datetime.fromtimestamp(time.time())
print(f"{dt.year}/{dt.month}") # 2021/5
print(dt.strftime("%Y/%m")) # 2021/05 (当地时间)

Working with Time Deltas

1
2
3
4
5
6
7
8
9
10
11
from datetime import datetime, timedelta

dt1 = datetime(2020, 1, 1) + timedelta(days=1, seconds=1000)
print(dt1)
dt2 = datetime.now()

duration = dt2 - dt1
print(duration)
print("days", duration.days)
print("seconds", duration.seconds) # 不计天数
print("total_seconds", duration.total_seconds()) # 计天数

输出:

2020-01-02 00:16:40
497 days, 16:44:06.578196
days 497
seconds 60246
total_seconds 43001046.578196

Random Values

Generating Random Values

Demo 1

1
2
3
4
5
6
7
8
import random
import string

print(random.random())
print(random.randint(1, 10))
print(random.choice([1, 2, 3, 4])) # 从给定的值中随机选一个
print(random.choices([1, 2, 3, 4], k=4)) # 从给定的值中随机选出序列
print("".join(random.choices("abcdefg", k=4)))

输出:

0.9791978038762406
2
3
[4, 1, 3, 3]
eefe

Demo 2

1
2
3
4
5
6
import random
import string

print(string.ascii_letters) # 所有字母
print(string.digits) # 所有数字
print("".join(random.choices(string.ascii_letters + string.digits, k=4)))

输出:

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
g02V

Demo 3:打乱顺序

1
2
3
4
5
import random

numbers = [1, 2, 3, 4]
random.shuffle(numbers)
print(numbers)

输出:

[4, 2, 3, 1]

Browser

Opening the Browser

1
2
3
4
import webbrowser

print("Deployment completed")
webbrowser.open("https://baidu.com")

Sending Emails

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from pathlib import Path
import smtplib

message = MIMEMultipart()
message["from"] = "name_of_sender"
message["to"] = "email_of_recipients@email.com"
message["subject"] = "This is a test"
message.attach(MIMEText("Body")) # 正文
message.attach(MIMEImage(Path("ww.jpg").read_bytes())) # 附件图片

with smtplib.SMTP(host="smtp.whu.edu.cn", port=25) as smtp:
smtp.ehlo() # say hello to smtp server
smtp.starttls() # TLS
smtp.login("email_of_sender@email.com", "password")
smtp.send_message(message)
print("Sent...")

Working with Templates

新建一个html文件 template.html,输入!回车会自动生成模板,删除head块中的内容,body块写入内容。最后如下:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>
Hi <strong>$name</strong>, this is our test email.
</body>

</html>

strong表示字体加粗。

在上述email例子中:

1
2
3
from string import Template

template = Template(Path("template.html").read_text()) # 读入模板
1
2
3
# 相应语句改为
body = template.substitute({"name": "John"}) # 或者name="John"
message.attach(MIMEText(body, "html")) # "html"

即可。

Command-line Arguments

Demo 1

1
2
3
import sys

print(sys.argv)

>python app.py -a -b -c

[‘app.py’, ‘-a’, ‘-b’, ‘-c’]

Demo 2

1
2
3
4
5
6
7
import sys

if len(sys.argv) == 1:
print("USAGE: python3 app.py <password>")
else:
password = sys.argv[1]
print("password", password)

> python app.py

USAGE: python3 app.py <password>

> python app.py 1234

password 1234

Running External Programs

Python执行命令

在 window 10 上跑的。

用python 执行windows命令dir

1
2
3
4
5
6
7
import subprocess

completed = subprocess.run(["dir", "."],
shell=True,
capture_output=True,
text=True)
print(type(completed))

capture_output=True使得输出在completed.stdout。

输出:

<class ‘subprocess.CompletedProcess’>

1
2
3
4
print("args", completed.args)
print("returncode", completed.returncode) # 0: success
print("stderr", completed.stderr) # standard error
print("stdout", completed.stdout) # standard output

输出:

> python app.py

args [‘dir’, ‘.’]
returncode 0
stderr
stdout 驱动器 E 中的卷没有标签。
卷的序列号是 000E-D27B

E:\Stone\Python\HelloWorld 的目录

2021/05/13 19:24 <DIR> .
2021/05/13 19:24 <DIR> ..
2021/05/06 16:44 <DIR> .vscode
2021/05/13 19:24 341 app.py
2021/05/06 16:15 8 content.txt
2021/05/13 15:36 54 data.csv
2021/05/13 15:55 0 db.sqlite3
2021/05/12 18:49 <DIR> ecommerce
2021/05/13 15:27 <DIR> extract
2021/05/13 14:42 3,647 files.zip
2021/05/13 15:48 102 movies.json
2021/05/13 18:03 138 template.html
2021/05/13 17:42 78,556 ww.jpg
2021/05/12 18:12 <DIR> __pycache__
8 个文件 82,846 字节
6 个目录 46,196,027,392 可用字节

Python执行另一个python脚本

1
2
# other.py
print("Here is a complicated script.")
1
2
3
4
5
6
7
8
9
10
11
# app.py
import subprocess

completed = subprocess.run(["python", "other.py"],
shell=True,
capture_output=True,
text=True)
print("args", completed.args)
print("returncode", completed.returncode) # 0: success
print("stderr", completed.stderr) # standard error
print("stdout", completed.stdout) # standard output

> python app.py

args [‘python’, ‘other.py’]
returncode 0
stderr
stdout Here is a complicated script.

看到 stdout 就是 other.py 的输出。

错误命令

1
2
3
4
5
6
7
8
9
10
import subprocess

completed = subprocess.run(["False"],
shell=True,
capture_output=True,
text=True)
print("args", completed.args)
print("returncode", completed.returncode) # 0: success
print("stderr", completed.stderr) # standard error
print("stdout", completed.stdout) # standard output

> python app.py

args [‘False’]
returncode 1
stderr ‘False’ 不是内部或外部命令,也不是可运行的程序
或批处理文件。

stdout

1
2
if completed.returncode != 0:		# 可以这样判断处理
print(completed.stderr)

也可以这样处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import subprocess

try:
completed = subprocess.run(["False"],
shell=True,
capture_output=True,
text=True,
check=True) # 自动检查
print("args", completed.args)
print("returncode", completed.returncode) # 0: success
print("stderr", completed.stderr) # standard error
print("stdout", completed.stdout) # standard output

except subprocess.CalledProcessError as ex:
print(ex)

输出:

Command ‘[‘False’]’ returned non-zero exit status 1.