前言
本文介绍如何使用 Python 实现自动化办公,减少人工参与。通过本教程,你可以学习到利用 Python 对常用办公工具进行自动化处理的方法。
本文介绍使用 Python 进行自动化办公的技术方案,涵盖文件与文件夹管理(shutil、os、glob)、Word 文档读写(python-docx)、Excel 数据处理(xlrd、xlsxwriter)、PPT 演示文稿操作(python-pptx)以及邮件发送(smtplib、schedule)。内容包括代码示例、样式设置、图表生成及常见问题排查,旨在帮助开发者提升办公效率。

本文介绍如何使用 Python 实现自动化办公,减少人工参与。通过本教程,你可以学习到利用 Python 对常用办公工具进行自动化处理的方法。
首先学习普通的文件操作。像 .txt 等可以直接打开查看内容的文件属于普通文件。而 .docx / .xlsx / .psd 等需要特定软件打开的文件则不同。
除了 os 模块,我们还可以使用更细粒度的 shutil 模块来操作文本文件。
shutil 是 python 3.8 的内置模块,如果你正好 >= 这个版本,就不需要额外安装。
使用 shutil 模块帮助进行文件的复制。
导入包与模块:
from shutil import copy
使用方法:copy(来源文件,目标地址)。
这里要注意,来源文件一定要是一个绝对路径或相对路径,而目标地址可以不包含具体的文件名。
代码演示:将 test1.txt 复制到 test1 文件夹下。
如何进行文件内容的复制?shutil 有专门的函数 copyfile。
导入包与模块:
from shutil import copyfile
使用方法:copyfile(来源文件,目标文件)。
区别在于:copy 的目标可以是一个文件夹也可以是一个文件,而 copyfile 只能是一个文件。
所谓文件的移动就是从一个目标路径的文件 A 移动到目标路径 B 中去。A 和 B 名称可能相同也可能不同。移动后 A 路径下不存在该文件,只存在于 B 路径下。
它支持将目标 A 路径下的文件名称进行改变,所以也是一个变相的重命名。
导入包与模块:
from shutil import move
使用方法:move(来源地址,目标地址)。
代码演示:
# coding:utf-8
import os
from shutil import move
# 获取来源文件路径
path = os.path.join(os.getcwd(), 'xxx.txt')
# 获取目标地址
target = os.path.join(os.getcwd(), 'test1')
# 将 xxx.txt 文件移动到 test1 目录下并重命名
move(path, target+'/abc.txt')
在 shutil 中,其实不支持单独的文件删除,可以使用 os 包中的 remove 方法。
导入包与模块:
import os
使用方法:os.remove(目标文件)。
先来看看文件压缩的函数。
导入包与模块:
from shutil import make_archive
使用方法:make_archive(压缩之后的文件名,压缩后缀,希望压缩的文件或目录)。
返回值:生成的压缩包地址。
解压压缩包:
导入包与模块:
from shutil import unpack_archive
使用方法:unpack_archive(要解压的文件,解压后的路径)。
文件的查找借助 glob 包来实现。glob 是一个快速查找文件夹中内容的包,可以通过模糊查找的形式找到想要的内容。
导入包与模块:
from glob import glob
使用方法:glob(任意目录)。
返回内容:指定路径下的内容列表,不存在的路径返回空列表。
*号代表查询当前文件下所有文件。也可以在通配符后面加上我们要查询的文件格式,或者直接指定要查找的文件。
如果知道文件名但不知道位置,可以使用递归方式查找。
# coding:utf-8
import os
from glob import glob
path = os.path.join(os.getcwd(), '*')
final_result = []
def search(path, target):
result = glob(path)
for data in result:
if os.path.isdir(data): # 如果是一个目录
_path = os.path.join(data, '*')
print('%s is filepath' % data)
search(_path, target) # 继续往下找
else: # 如果不是一个目录
if target in data:
final_result.append(data)
return final_result
if __name__ == '__main__':
result = search(path, target='abc.txt')
print(result)
文件中包含某些关键字,但是我们知道文件名和所在路径,该如何查找呢?
代码编写:
# coding:utf-8
import os
from glob import glob
path = os.path.join(os.getcwd(), '*')
final_result = []
def search(path, target):
result = glob(path)
for data in result:
if os.path.isdir(data): # 如果是一个目录
_path = os.path.join(data, '*')
print('%s is filepath' % data)
search(_path, target)
else: # 如果不是一个目录
f = open(data, 'r', encoding='utf-8')
try:
content = f.read()
if target in content:
final_result.append(data)
except:
print('data read failed: %s' % data)
continue
finally:
f.close()
return final_result
if __name__ == '__main__':
result = search(path, target='YiQie99903')
print(result)
这段代码查找一个目录(和子目录)下的所有文件,并在文件中搜索包含指定字符串的文件。
在日常使用中,会产生一些重复的文件占用硬盘空间。我们可以从指定路径开始读取,利用 glob 读取每个文件夹,记录名称和大小,判断是否重复,相同则删除。
# coding:utf-8
import glob
import hashlib
import os
data = {}
def clear(path):
result = glob.glob(path)
for _data in result:
if os.path.isdir(_data):
_path = os.path.join(_data, '*')
clear(_path)
else:
name = os.path.split(_data)[-1]
if_byte = False
if 'zip' in name:
if_byte = True
f = open(_data, 'rb')
else:
f = open(_data, 'r', encoding='utf-8')
content = f.read()
f.close()
if if_byte:
hash_content_obj = hashlib.md5(content)
else:
hash_content_obj = hashlib.md5(content.encode('utf-8'))
hash_content = hash_content_obj.hexdigest()
if name in data:
sub_data = data[name]
is_delete = False
for k, v in sub_data.items():
if v == hash_content:
os.remove(_data)
print('%s will delete' % _data)
is_delete = True
if not is_delete:
data[name][_data] = hash_content
else:
data[name] = {
_data: hash_content
}
if __name__ == '__main__':
path = os.path.join(os.getcwd(), '*')
clear(path)
print(path)
for k, v in data.items():
print(k)
通过循环,将目标字符串加入到文件名并进行修改。
# coding:utf-8
import glob
import shutil
import os
def update_name(path):
result = glob.glob(path)
for index, data in enumerate(result):
if os.path.isdir(data):
_path = os.path.join(data, '*')
update_name(_path)
else:
path_list = os.path.split(data)
name = path_list[-1]
new_name = '%s_%s' % (index, name)
new_data = os.path.join(path_list[0], new_name)
shutil.move(data, new_data)
if __name__ == '__main__':
path = os.path.join(os.getcwd(), '*')
update_name(path)
前面学习了文件的管理,现在学习如何使用 shutil 实现对文件夹的管理。
导入包与模块:
from shutil import copytree
使用方法:copytree(来源目录,目标目录)。
导入包与模块:
from shutil import rmtree
使用方法:rmtree(目标目录)。
值得注意的是,目标目录一定要存在,否则会报错。
导入包与模块:
from shutil import move
使用方法:move(来源目录,目标目录)。
如果目标目录不存在,那就是对原来的目录进行重命名。而且还可以移动的同时并重命名。
move(path, target+'/test4') # 移动并重命名
接下来学习如何使用 Python 来操作 Word 文档,这里介绍 python-docx。
要想使用 python-docx,要先进行下载安装。
pip install python-docx
读取 Word 文档,用到 python-docx 之 Document。
首先要导入包和模块:
from docx import Document
使用方法:Document(word 地址)。
返回值:Word 文件对象。
段落内容的读取:
# coding:utf-8
from docx import Document
# docx 只支持 .docx 这样的格式 如果是 doc 请转换成 docx
doc = Document('test.docx')
for p in doc.paragraphs:
print(p.text)
表格内容的读取:
# coding:utf-8
from docx import Document
doc = Document('test.docx')
for t in doc.tables:
for row in t.rows:
_row_str = ''
for cell in row.cells:
_row_str += cell.text + ','
print(_row_str)
批量读取每一个 Word(通过 glob 获取 Word 信息),将他们所有的可读内容获取,并通过关键字方式筛选,拿到目标简历地址。
# coding:utf-8
import glob
from docx import Document
class ReadDoc(object):
def __init__(self, path):
self.doc = Document(path)
self.p_text = ''
self.table_text = ''
self.get_para()
self.get_table()
def get_para(self):
for p in self.doc.paragraphs:
self.p_text += p.text + '\n'
def get_table(self):
for table in self.doc.tables:
for row in table.rows:
_cell_str = ''
for cell in row.cells:
_cell_str += cell.text + ','
self.table_text += _cell_str + '\n'
def search_word(path, targets):
result = glob.glob(path)
final_result = []
for i in result:
isuse = True
if os.path.isfile(i):
if i.endswith('.docx'):
doc = ReadDoc(i)
p_text = doc.p_text
t_text = doc.table_text
all_text = p_text + t_text
for target in targets:
if target not in all_text:
isuse = False
break
if not isuse:
continue
final_result.append(i)
return final_result
if __name__ == '__main__':
path = os.path.join(os.getcwd(), '*')
res = search_word(path, ['Java', '本科'])
print(res)
通过 Python 脚本自动生成一个 Word 文档。内容包括标题、段落、图片、表格、分页。
# coding:utf-8
from docx import Document
doc = Document()
# 添加标题 参数:标题内容,标题样式等级
title = doc.add_heading('My title', 0)
# 追加内容
title.add_run('\n Sample Text')
# 生成 word 文档
doc.save('test.docx')
# coding:utf-8
from docx import Document
doc = Document()
title = doc.add_heading('My title', 0)
p = doc.add_paragraph('欢迎来到这里学习 python')
p.add_run('\nSample Content')
doc.save('test.docx')
# coding:utf-8
from docx import Document
from docx.shared import Inches
doc = Document()
title = doc.add_heading('My title', 0)
image = doc.add_picture('这是一张图片.png', width=Inches(5), height=Inches(5))
doc.save('test.docx')
# coding:utf-8
from docx import Document
from docx.shared import Inches
doc = Document()
title = doc.add_heading('My title', 0)
# 表格内容
title_list = ['name', 'age', 'sex']
# 生成表格 参数:行数 列数
table = doc.add_table(rows=1, cols=3)
# 插入参数
title_cells = table.rows[0].cells
title_cells[0].text = title_list[0]
title_cells[1].text = title_list[1]
title_cells[2].text = title_list[2]
# 追加内容
data = [
('一切', '2', '男'),
('总会', '2', '男'),
('归于平淡', '4', '男')
]
for d in data:
row_cells = table.add_row().cells
row_cells[0].text = d[0]
row_cells[1].text = d[1]
row_cells[2].text = d[2]
doc.save('test.docx')
# coding:utf-8
from docx import Document
doc = Document()
title = doc.add_heading('My title', 0)
doc.add_page_break()
title2 = doc.add_heading('My title2', 0)
doc.save('test.docx')
# coding:utf-8
from docx import Document
from docx.shared import RGBColor, Pt
doc = Document()
style = doc.styles['Normal']
style.font.name = '微软雅黑'
style.font.color.rgb = RGBColor(255, 0, 0)
style.font.size = Pt(16)
# coding:utf-8
from docx import Document
from docx.shared import RGBColor, Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
doc = Document()
title = doc.add_heading('My title', 0)
title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
title.style.font.size = Pt(50)
_t = title.add_run('\n Sample Text')
_t.italic = True
_t.bold = True
p = doc.add_paragraph('欢迎来到这里学习 python')
p.add_run('\nSample Content').italic = True
p.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
doc.save('test.docx')
不能直接对图片进行样式改造,需要借助段落帮助我们才行。
# coding:utf-8
from docx import Document
from docx.shared import RGBColor, Pt, Inches
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_ALIGN_PARAGRAPH
doc = Document()
title = doc.add_heading('My title', 0)
title.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
title.style.font.size = Pt(50)
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
_p = p.add_run()
image = _p.add_picture('这是一张图片.png', width=Inches(3), height=Inches(2))
doc.save('test.docx')
for i in doc.styles:
if i.type == doc.styles.WD_STYLE_TYPE.TABLE:
print(i.name)
以上都是表格样式,我们挑一两个来试试。
认识一下 PDF 工具包 - pdfkit。
pip install pdfkit
安装好 pdfkit 后,还需要一个依赖的工具 wkhtmltopdf。
pdfkit.from_url('网址','保存的路径')
代码演示:
# coding:utf-8
import pdfkit
config = pdfkit.configuration(wkhtmltopdf=r"D:\installPath\wkhtmltopdf\bin\wkhtmltopdf.exe")
pdfkit.from_url('https://www.baidu.com', 'baidu.pdf', configuration=config)
# coding:utf-8
import pdfkit
config = pdfkit.configuration(wkhtmltopdf=r"D:\installPath\wkhtmltopdf\bin\wkhtmltopdf.exe")
htmlStr = """<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>Sample Title</h1>
</body>
</html>"""
pdfkit.from_string(htmlStr, 'sample.pdf', configuration=config)
安装一个新的依赖包:
pip install pydocx
代码演示:
# coding:utf-8
import pdfkit
from pydocx import PyDocX
config = pdfkit.configuration(wkhtmltopdf=r"D:\installPath\wkhtmltopdf\bin\wkhtmltopdf.exe")
html = PyDocX.to_html('resume.docx')
f = open('html1.html', 'w')
f.write(html)
f.close()
pdfkit.from_file('html1.html', 'resume.pdf', configuration=config)
html2 = PyDocX.to_html('resume2.docx')
pdfkit.from_string(html2, 'resume2.pdf', configuration=config)
注意,pdfkit 库需要 wkhtmltopdf 工具来进行转换。因此,你需要在代码中指定 wkhtmltopdf 工具的位置。
接下来学习 Python 对 Excel 的操作,这里给大家介绍一个新模块 xlrd。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xlrd==1.2.0
为什么指定版本呢?因为更高的版本有可能会发生不兼容的情况。
使用方法:book = xlrd.open_workbook(excel 文件)。
返回:excel 对象。
| 函数名 | 说明 |
|---|---|
| book.sheet_by_name() | 按照工作薄名称获取 |
| book.sheet_by_index() | 按照索引获取 |
| book.sheets() | 获取所有工作薄列表 |
代码编写:
# coding:utf-8
import xlrd
excel = xlrd.open_workbook('user_detail.xlsx')
# 按照工作薄名称获取
book = excel.sheet_by_name('用户明细')
print(book.name)
# 按照索引获取
book = excel.sheet_by_index(0)
print(book.name)
# 获取所有的工作簿列表
for i in excel.sheets():
print(i.name)
| 函数名 | 说明 |
|---|---|
| sheet.nrows | 返回总行数 |
| sheet.ncols | 返回总列数 |
| sheet.get_rows() | 返回每行内容列表 |
代码执行:
# coding:utf-8
import xlrd
excel = xlrd.open_workbook('user_detail.xlsx')
book = excel.sheet_by_name('用户明细')
print(book.name)
print('%s 行' % book.nrows)
print('%s 列' % book.ncols)
for i in book.get_rows():
content = []
for j in i:
content.append(j.value)
print(content)
学习 Python 对 Excel 写入数据的操作,这里给大家介绍一个新模块 xlsxwriter。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xlsxwriter
| 函数名 | 说明 | 参数 |
|---|---|---|
| xlsxwriter.Workbook() | 生成 excel 对象 | Excel 文件名 |
| add_worksheet() | 添加工作薄 | 工作薄名称 |
| sheet.write() | 书写内容 | 行索引,列索引,内容 |
| book.close() | 关闭 excel 对象 | 无 |
import xlrd
import xlsxwriter
def read():
result = []
excel = xlrd.open_workbook('user_detail.xlsx')
book = excel.sheet_by_name('用户明细')
for i in book.get_rows():
content = []
for j in i:
content.append(j.value)
result.append(content)
return result
def write(content):
excel = xlsxwriter.Workbook('test.xlsx')
book = excel.add_worksheet("test")
for index, data in enumerate(content):
for sub_index, sub_date in enumerate(data):
book.write(index, sub_index, sub_date)
excel.close()
if __name__ == '__main__':
result = read()
write(result)
| 函数名 | 说明 | 参数 |
|---|---|---|
| add_chart() | 创建图表对象 | {type: 样式} |
| add_series() | 定义需要展示的数据 | 字典 |
| set_title() | 定义图表 title | 字符串 |
add series() 的参数:
| 参数 | 说明 | 值 |
|---|---|---|
| categories | 展示的标题 | =Sheet1!1:4 |
| values | 展示的数据 | =Sheet1!1:4 |
| name | 表名 |
| 样式名 | 说明 |
|---|---|
| area | 区域样式表 |
| bar | 条形样式 |
| column | 柱状样式 |
| line | 线条样式 |
| pie | 饼图样式 |
| doughnut | 圆环样式 |
| scatter | 散点样式 |
| stock | 库存样式 |
| radar | 雷达样式 |
import xlsxwriter
excel = xlsxwriter.Workbook('test.xlsx')
book = excel.add_worksheet('用户角色')
data = [
['社区成员', '社区之星', '社区管理员', '区长'],
[20, 23, 2, 1]
]
book.write_column('A1', data[0])
book.write_column('B1', data[1])
chart = excel.add_chart({'type': 'pie'})
chart.add_series({
'categories': '=用户角色!$A1:$A4',
'values': '=用户角色!$B1:$B4',
'name': '角色占比'
})
chart.set_title({
'name': '角色占比图表'
})
book.insert_chart('A7', chart)
excel.close()
从现在开始学习 PPT 的自动化操作。这里用到 python-pptx。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-pptx
import pptx
p = pptx.Presentation()
layout = p.slide_layouts[7]
slide = p.slides.add_slide(layout)
p.save('test.ppt')
布局是指幻灯片的外观,一共有 11 种布局(可能跟版本有关)。使用 pptx.Presentation.slides.add_slide() 方法可以向幻灯片集合添加一张幻灯片,这个方法需要指定一个布局。
import pptx
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_PARAGRAPH_ALIGNMENT
from pptx.util import Pt
p = pptx.Presentation()
layout = p.slide_layouts[1]
slide = p.slides.add_slide(layout)
title = slide.placeholders[0]
title.text = 'PPT 自动化'
placeholder = slide.placeholders[1]
placeholder.text = 'Sample Text\nSample Content'
placeholder1 = placeholder.text_frame.add_paragraph()
placeholder1.text = '点赞'
placeholder1.font.bold = True
placeholder1.font.italic = True
placeholder1.font.size = Pt(16)
placeholder1.font.underline = True
placeholder1.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER
placeholder2 = placeholder.text_frame.add_paragraph()
placeholder2.text = '转发'
placeholder2.font.size = Pt(32)
placeholder2.alignment = PP_PARAGRAPH_ALIGNMENT.RIGHT
placeholder2.font.color.rgb = RGBColor(255, 0, 0)
p.save('test.ppt')
import pptx
from pptx.util import Inches
p = pptx.Presentation()
layout = p.slide_layouts[1]
slide = p.slides.add_slide(layout)
title = slide.placeholders[0]
title.text = 'PPT 自动化'
placeholder = slide.placeholders[1]
placeholder.text = 'Sample Text'
layout = p.slide_layouts[1]
slide = p.slides.add_slide(layout)
title = slide.placeholders[0]
title.text = '第二页'
rows = 10
cols = 2
left = top = Inches(2)
width = Inches(6.0)
height = Inches(1.0)
table = slide.shapes.add_table(rows, cols, left, top, width, height).table
for index, _ in enumerate(range(rows)):
for sub_index in range(cols):
table.cell(index, sub_index).text = '%s:%s' % (index, sub_index)
layout = p.slide_layouts[6]
slide = p.slides.add_slide(layout)
image = slide.shapes.add_picture(
image_file='C:\\Users\\Desktop\\cover.jpg',
left=Inches(1),
top=Inches(1),
width=Inches(6),
height=Inches(6)
)
p.save('test.ppt')
# coding:utf-8
import pptx
p = pptx.Presentation('test.ppt')
for slide in p.slides:
for shape in slide.shapes:
if shape.has_text_frame:
print(shape.text_frame.text)
if shape.has_table:
for cell in shape.table.iter_cells():
print(cell.text)
接下来学习 Python 对邮件的操作。
发送邮件的流程包括连接服务器、登录、构建邮件内容、发送。
常见的邮件协议有:
登录邮箱设置,开启 POP3/SMTP/IMAP 服务,获取授权码。
# coding:utf-8
import smtplib
from email.header import Header
from email.mime.text import MIMEText
mail_host = 'smtp 服务器'
mail_user = '你的邮箱'
mail_pass = '密钥'
sender = '发送人的邮箱'
receivers = ['接收者的邮箱']
message = MIMEText('这是一个测试', 'plain', 'utf-8')
message['From'] = Header(sender)
message['Subject'] = Header('python 脚本测试', 'utf-8')
try:
smtpobj = smtplib.SMTP()
smtpobj.connect(mail_host, 25)
smtpobj.login(mail_user, mail_pass)
smtpobj.sendmail(sender, receivers, message.as_string())
except smtplib.SMTPException as e:
print('error: %s' % e)
# coding:utf-8
import smtplib
from email.header import Header
from email.mime.text import MIMEText
mail_host = 'smtp 服务器'
mail_user = '你的邮箱'
mail_pass = '密钥'
sender = '发送人的邮箱'
receivers = ['接收者的邮箱']
message = MIMEText('<p style="color:red;">这是一个测试</p>', 'html', 'utf-8')
message['From'] = Header(sender)
message['Subject'] = Header('python 脚本测试', 'utf-8')
try:
smtpobj = smtplib.SMTP()
smtpobj.connect(mail_host, 25)
smtpobj.login(mail_user, mail_pass)
smtpobj.sendmail(sender, receivers, message.as_string())
except smtplib.SMTPException as e:
print('error: %s' % e)
# coding:utf-8
import smtplib
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
mail_host = 'smtp 服务器'
mail_user = '你的邮箱'
mail_pass = '密钥'
sender = '发送人的邮箱'
receivers = ['接收者的邮箱']
message = MIMEMultipart()
message['From'] = Header(sender)
message['Subject'] = Header('python 脚本测试', 'utf-8')
attr = MIMEText(open('test.ppt', 'rb').read(), 'base64', 'utf-8')
attr['Content-Type'] = 'application/octet-stream'
attr['Content-Disposition'] = 'attachment;filename="test.ppt"'
message.attach(attr)
message.attach(MIMEText('这是一个带附件的邮件', 'plain', 'utf-8'))
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25)
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
except smtplib.SMTPException as e:
print('error: %s' % e)
使用 schedule 库。
pip install schedule
Python 的 schedule 库支持以下时间格式:
| 时间格式 | 描述 |
|---|---|
| @once | 在程序启动时运行一次 |
| @hourly | 每小时运行一次 |
| @daily | 每天运行一次 |
| @weekly | 每周运行一次 |
| @monthly | 每月运行一次 |
| @yearly | 每年运行一次 |
| @cron | 使用 crontab 格式 |
| datetime object | 使用 Python 的 datetime 对象 |
例如,每周一的 00:00 运行一次任务:
# coding:utf-8
import smtplib
import time
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import schedule
mail_host = 'smtp 服务器'
mail_user = '你的邮箱'
mail_pass = '密钥'
sender = '发送人的邮箱'
receivers = ['接收者的邮箱']
message = MIMEMultipart()
message['From'] = Header(sender)
message['Subject'] = Header('python 脚本测试', 'utf-8')
attr = MIMEText(open('test.ppt', 'rb').read(), 'base64', 'utf-8')
attr['Content-Type'] = 'application/octet-stream'
attr['Content-Disposition'] = 'attachment;filename="test.ppt"'
message.attach(attr)
message.attach(MIMEText('这是一个带附件的邮件', 'plain', 'utf-8'))
def send():
try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host, 25)
smtpObj.login(mail_user, mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
except smtplib.SMTPException as e:
print('error: %s' % e)
if __name__ == '__main__':
schedule.every().monday.at("00:00").do(send)
while True:
schedule.run_pending()
time.sleep(60)
也可以使用 crontab 格式来指定更精细的时间,例如每隔 10 秒运行一次:
if __name__ == '__main__':
schedule.every(10).seconds.do(send)
while True:
schedule.run_pending()
time.sleep(60)
在上面的代码中,while 循环被用来不断检查是否有挂起的任务需要执行。schedule 库会将任务添加到挂起任务列表中,然后使用 schedule.run_pending() 函数来检查是否有挂起任务的执行时间已经到了。
错误原因:运行 debug 调试找到 socket.py 这个文件的第 676 行,name 参数编码错误。这个 name 参数来自于计算机的名称,如果计算机名称包含非 ASCII 字符(如中文),可能会报错。
解决方法:建议将计算机名称改成英文字母,很多涉及到网络的代码都会报编码错误。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online