之前我们已经学习过变量、函数、和类。这些都是Python模块的重要组成部分。而模块,是Python世界里最高级别的程序组织单元,其功能和类、函数都有些相似,封装模块的目的也是为了把程序代码和数据存放起来以便再次利用。模块可以封装任何的数据和代码,每一个.py文件都是一个python的模块。
模块的封装相比于函数和类,拥有更广泛的用途,其内容在本模块和其他任意模块中都可以进行调用,因此也更容易共享。于是,使用模块主要有两种方式,一种是自己建立模块并使用,另外一种是使用他人共享的模块。以下我们对封装模块的引用做具体讲述:
建立一个test.py的文件:
# test.py文件
print('这里是test模块')
def exp():
print('这里是test模块的exp函数')
class Exam:
name = 'exam'
def module (self):
print('这里是test模块的Exam类')
这就是一个简单的模块。
这个模块封装好后,我们就可以在其他模块中对它进行引用,引用格式为:
import 待引用文件名
之后,我们就可以使用引用模块内的全部内容。下面我们再创建一个.py文件,引用刚才的test.py文件,并具体介绍如何引用函数和类:
①直接使用引用模块函数
这种方式会直接调用模块内的函数,输出结果。这样使用函数时必须带上"test."这个前。 示例如下:
import test
# 在其他模块中引用test模块
test.exp()
# 格式为:引用模块的文件名.函数名(形参)
# 结果为:这里是test模块
# 这里是test模块的exp函数
如果前缀太长,频繁使用该模块内容时书写就会变的麻烦,我们可以采用以下的方式降低书写难度:
import test as s
s.exp()
# 输出为:这里是test模块
# 这里是test模块的exp函数
需要注意的一点是,这样的书写方式,计算机将不再认识test. 这个前缀,只能使用s. 作为前缀。
②转化原函数并使用
这种方式不会直接运行函数,我们可以为其重新取名,而后就可以用新名字来调用该函数:
import test
work=test.exp
# 定义新的函数名
work()
# 可以使用新的函数名调用函数
# 结果为:这里是test模块
# 这里是test模块的exp函数
这种方式调用函数更为方便,并且可以根据调用函数的具体用途为其重新命名,合理运用可以提高代码的可读性。
③引用模块的类
import test
# 直接使用类
print(test.Exam().name)
test.Exam.module()
# 结果为:这里是test模块
# exam
同样地,我们可以通过将该类实例化的方式引用:
import test
att=test.Exam()
# 实例化Exam()类
print(att.name)
att.module()
# 结果为:这里是test模块
# 这里是test模块的exp函数
# exam
# 这里是test模块的Exam类
至此,引用整个模块的细节基本就介绍完了。
使用 import 语句导入一个模块,最主要的目的并不是运行模块中的执行语句,而是为了利用模块中已经封装好的变量、函数、类。因此很多时候我们不需要将整个模块进行引用,只需要引用特定的部分。这就需要用到from…import语句。
from…import语句的使用格式为:
form 模块名 import 指定模块的函数名、类名或变量名
我们以test.py文件作为封装好的模块,以引用exp()函数为例:
# 从import模块中引module函数
from test import exp
exp()
# 结果为:这里是test模块
# 这里是test模块的exp函数
可以看到,用 from…import 语句引用的内容在使用时不必加“模块名.”作为前缀。对类和变量的引用也是如此:
from test import Exam
att=Exam()
att.module()
# 引用Exam类的module()方法
print()
# 打印一个换行作为分隔
from test import exp
exp()
# 引用函数exp()
# 输出为:这里是test模块
# 这里是test模块的Exam类
#
# 这里是test模块的exp函数
我们发现了一个有趣的现象,不管是用import函数对整个模块进行引用还是使用from…import引用模块的一部分,都会使test文件的运行部分执行一次。而此后如果在这个文件内再次引用test模块或其部分内容,test的运行部分不会再次执行。这是因为第一次引用内容时,计算机需要将test文件读一遍并记住,如果后面重复引用或引用其他部分时,计算机不再需要重新读取test文件。
通过上面的学习,我们知道引用是通过读取整个模块或模块的一部分到另一个模块的操作。而被引用的模块也可以让某一部分内容拒绝被读取,这就需要用到if __ name__==’__ main__'语句。下面我们对test模块进行一点改动:
# test.py文件
if __name__=='__main__':
print('这里是test模块')
def exp():
print('这里是test模块的exp函数')
class Exam:
name = 'exam'
def module (self):
print('这里是test模块的Exam类')
这样修改之后,运行test文件输出的结果是:这里是test模块
然后再在另一个模块引用test模块,就不会看到刚才的结果输出,如:
import test
test.exp()
# 输出为:这里是test模块的exp函数
不难看出,if __ name__==’__ main__‘语句所在的模块直接运行时,其后面的语句会被执行,而其他模块对其进块引用,这个语句后面的内容不会执行。需要注意的是,这个’__ main__'写法是固定的,不可以改成文件名,否则其后的内容永远不会执行。
在Python中,有许多内置模块可以帮助我们实现很多功能。使用这些模块的核心是搞清楚模块的功能,也就是模块中的函数和类有什么作用,以及具体如何使用。当有没见过的功能需要实现时,我们可以通过百度进行查询是否有对应的内置模块或函数,也可以去Python的官方网站进行查询。直接在搜索栏寻找或点击标准库参考,通用操作系统服务进行学习。
以下我们学习两个简单实用的模块,揭示如何使用python操作文档、发送邮件。
csv 是一种文件格式,可以简单理解成“简易版的 excel。学会这个模块可以应用程序处理简单的电子表格。对这个电子表格的操作与对.txt文件的操作有所不同,但也十分相似。
首先,我们找到pycharm中.py文件的存放位置,然后新建一个文档格式的文件,并写入一些内容:
之后我们将其保存为.csv格式,点击文件—另存为:
在保存类型之中修改为csv文件。不要直接以重命名的方式修改拓展名,否则可能导致在pycharm中无法正常输出。
然后我们在pycharm中打开它,打开它所使用的函数依然是open(),并且模式也和操作.txt文件很像,甚至强大的辅助函数seek()使用方法也是一样的。但读取和写入时所用的函数及书写的方式就明显不同于.txt文档了。我们先举例说读取文件的reader()函数的用法:
with open('xxx.csv','r',encoding='utf-8-sig') as a:
read=csv.reader(a)
并且,reader()函数为csv模块的读取函数,其返回值为_csv.reader类型的数据,因此直接对返回值进行打印,其结果不是我们想要的内容。想要打印文档的内容正确的方法如下:
import csv
with open("edu.csv", encoding='utf-8-sig') as edu:
# 默认的模式为'r',可以不写
content = csv.reader(edu)
# 使用reader()方法,创建一个content对象
print('content的类型为:',end='')
print(type(content))
for c in content:
# 如果写成for c in edu:也会有结果输出,可以自行尝试,对比一下
# 遍历content对象的每一行
print('c的类型为:',end='')
print(type(c))
# 查看c的数据类型
print(c)
我们需要指定编码方式为“utf-8-sig”,如果没有“-sig”,会引起输出的结果出现问题。模式默认为’r’(只读)。我们先观察输出的结果:
从结果中不难看出,content是将csv文件的每一行都以一个列表进行存储,文档有多少行就会产生多少个数组,并且数组内的元素是str类型。
写入文件需要使用writerow()函数,其参数类型为数组。不难想到,我们只能一行一行的去写,因此很多情况下需要多次使用writerow()函数。我们还是先上例子:
import csv
with open("edu.csv", 'w+', encoding='utf-8-sig') as edu:
writer = csv.writer(edu)
writer.writerow([13,21,12])
writer.writerow([11,15,42])
writer.writerow([58,69,97])
edu.seek(0)
read = csv.reader(edu)
for a in read:
print(a)
我们看到输出的结果:
一共有六个数组。打开csv文件查看,结果也是这样:
那么如何才能去掉这些空行呢?可以在open函数里加上一句newline=’’,如下:
import csv
with open("edu.csv", 'w+', encoding='utf-8-sig',newline='') as edu:
writer = csv.writer(edu)
writer.writerow([13,21,12])
writer.writerow([11,15,42])
writer.writerow([58,69,97])
Python可以实现发送邮件的功能,依赖于smtplib和email两个内置模块。其中,smtplib 是用来发送邮件用的,email 是用来构建邮件内容的。下面我们介绍如何使用pycharm发送邮件。发送邮件的代码普适性比较强,
这一节我们先学习发送最基础的邮件,即只有正文内容的邮件。先看代码:
import smtplib
server = smtplib.SMTP()
server.connect(host, port,'utf-8')
server.login(username, password)
server.sendmail(sender, to_addr, msg.as_string())
server.quit()
这段代码可以帮助我们实现发送简单的邮件功能,下面我们进行逐句讲解:
import smtplib
第一行,引用smtplib模块
server = smtplib.SMTP()
第二行,SMTP 是 “简单邮件传输协议” 的意思,SMTP 协议是由源服务器到目的地服务器传送邮件的一组规则。我们可以简单理解为通过 SMTP 指定一个服务器,然后把邮件送到另一个服务器。
server.connect(host, port,'utf-8')
第三行,表示连接(connect)指定的服务器。其中,host参数是指定服务器的地址,通过百度搜索 “xx 邮箱服务器地址”,就可以找到。port参数是端口,端口属于计算机网络知识里的内容,可以自行搜索了解,此处指需要知道这个参数类型为整数即可。
server.login(username, password)
第四行,login意思为登录,即登录指定的服务器用的,需要输入登录邮箱的用户名(username)和授权码(password)两个参数。
server.sendmail(sender, to_addr, msg.as_string())
第五行,sendmail() 方法用于发送邮件,需要发件人,收件人和邮件内容三个参数。发件人 from_addr 与上面的 username 是一样的,都是登录邮箱。因此我们可以将 login() 方法中的 username 换成 from_addr,增加代码可读性。msg.as_string() 是一个字符串类型,其功能是将发送的信息 msg 变为字符串类型。具体用法会在后面实例中讲到,大家注意观察。
server.quit()
最后一行,server.quit() 是退出服务器,结束 SMTP 会话。
以QQ邮箱为例,发送一个邮件。首先查找SMTP服务器的地址:smtp.qq.com,端口为465 或 587。但是,由于 QQ 邮箱采用的加密方式是 SSL,所以要使用 SMTP_SSL 服务,因此需要对第二行的代码进行一定修改:
server = smtplib.SMTP_SSL()
QQ 邮箱一般默认关闭 SMTP服务,因此我们想使用,就得先去开启它。打开QQ邮箱进行登录,点击位于顶部的【设置】按钮,选择【账户】,然后下拉:
如图,将POP3/SMTP 服务打开。我们需要用密保手机发送短信,完成之后,QQ 邮箱会提供一个授权码,有了授权码,就可以在pycharm中用邮箱账号 + 授权码获取邮箱服务器的内容。
需要注意的是,授权码不是永久有效的,保持这个界面,就可以使用这个授权码在pycharm中进行操作,退出之后就需要重新获取授权码。
下面进行实战阶段。首先介绍email 模块:这个模块是用来写内容的模块,msg就出自这个模块。这个内容可以是纯文本、HTML 内容、图片、附件等多种形式,以满足我们对邮件发送的需求。我们定义下面三种名称:
MIMEText,内容形式为纯文本、HTML 内容
MIMEImage,内容形式为图片
MIMEMultipart,内容形式为多种组合,可包含文本和附件。
每种形式对应的导入方式为:
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
下面,我们把这段代码完善一下检测是否可以用pycharm发送一个简单的邮件:
import smtplib
from email.mime.text import MIMEText
# 采集信息
from_addr = input('请输入发件人的邮箱: ')
password = input('请输入发件人的 QQ 邮箱授权码: ')
to_addr = input('请输入收件人邮箱: ')
msg = MIMEText('send by python','plain','utf-8')
# 邮箱正文内容,第一个参数为内容,第二个参数为格式(plain 为纯文本),第三个参数为编码
try:
# 给到我们发送成功或失败的提示
server = smtplib.SMTP_SSL()
# 开启发信服务,这里使用的是加密传输
server.connect('smtp.qq.com', 465)
server.login(from_addr, password)
# 登录发信邮箱
server.sendmail(from_addr, to_addr, msg.as_string())
# 发送邮件
print('发送成功')
server.quit()
# 关闭服务器
except smtplib.SMTPException as e:
print('遇到错误',e)
正确填写信息后,我们会在输出栏看到提示:发送成功。打开收件人邮箱查看,确实收到了一封邮件:
通过之前的练习,我们已经可以发送邮件了。但是打开邮件之后我们发现里一个问题,这个邮件没有发件人信息,没有主题,正文内容太简单,显然不满足现在邮件的需求。下面我们进行一点改进:
①丰富开头和正文内容
邮件头(header)是这一块区域,包括主题、发件人、收件人等信息,接下来我们就需要补充邮件头header的代码:
from email.header import Header
# 用于构建邮件头
msg['From'] = Header(from_addr)
# 添加发送人信息
msg['To'] = Header(to_addr)
# 添加收件人信息,这种写法只能用于单发邮件
msg['Subject'] = Header('python test')
# 添加邮件主题
这段代码可以为我们发送的邮件润色,把它加到刚刚的代码中。仔细观察msg[’…’] 这种表达,是不是很像字典中根据键取值的表达?但是这里的 message 是一个 MIMEText 类的对象,msg[’…’] 就代表 MIMEText 类里面对应的属性。此外,我们还想要实现群发的功能,群发就需要一次写入很多收件地址,因此我们尝试用一个列表存储收件人信息再将这个列表作为收件人信息传递的方式发送邮件。但运行起来发现,Herder()不能解码列表。
msg['To'] = Header(to_addr)
直接将参数to_addr设置成存储收件人信息的列表,将无法成功运行。必须做出调整。通过查询发现Header() 接收的第一个参数的数据类型必须要是字符串或者字节,其类型为email.header.Header。运行下面代码进行测试:
from email.mime.text import MIMEText
from email.header import Header
addr='[email protected]'
msg = MIMEText('', 'plain', 'utf-8')
msg['To'] = Header(addr)
print(msg['To'])
print(type(msg['To']))
# 输出为:[email protected]
#
从结果中也不难看出,msg[‘To’]存储的数据不是列表类型。因此直接使用列表传递收件人信息行不通。通过查询了解到,我们需要把每个收件人信息用逗号连接起来,做成一个email.header.Header类型的数据,才能被正常读取。这就需要用到join()函数。我们先观察下面代码:
list_a=['a','b','c']
head='_'.join(list_a)
# 使用join()函数可以对列表类型数据操作,将其变为用指定字符(串)链接的字符串类型
print(head)
print(type(head))
head=',*/*—,'.join(list_a)
print(head)
print(type(head))
# 输出为:a_b_c
#
# a,*/*—,b,*/*—,c
#
这样就把一个列表变成了一串字符,也就满足了Header()接收数据的要求:
import smtplib
from email.mime.text import MIMEText
from email.header import Header
# 采集信息
from_addr = input('请输入发件人的邮箱: ')
password = input('请输入发件人的 QQ 邮箱授权码: ')
to_addrs = []
while True:
a=input('请输入收件人邮箱:')
# 输入收件人邮箱
to_addrs.append(a)
# 写入列表
b=input('是否继续输入,n退出,任意键继续:')
#询问是否继续输入
if b == 'n':
break
text = '''这里将写入邮件正文内容'''
msg = MIMEText(text, 'plain', 'utf-8')
# 设置邮件头信息
msg['From'] = Header(from_addr)
msg['To'] = Header(','.join(to_addrs))
# 这句是群发格式,单发也可以这样写
msg['Subject'] = Header('python test')
try:
server = smtplib.SMTP_SSL()
server.connect('smtp.qq.com', 465)
server.login(from_addr, password)
server.sendmail(from_addr, to_addrs, msg.as_string())
print('发送成功')
server.quit()
except smtplib.SMTPException as e:
print('遇到错误',e)
这样就比刚才完整多了。
前面我们已经介绍了如何发送完整的邮件,下面我们继续做一个拓展,利用Python发送带有附件和图片。还记得之前在文件操作里我们讲过的’rb’模式吗?现在就要派上用场了。先在路径下存一张图片,然后运行以下代码:
with open('example.png','rb') as a:
b=a.read()
print(b)
可以看到一串16进制数,是计算机以二进制读取图片的结果,这个结果可以用于发送邮件。由于这部分内容有固定的套路,我们直接上代码,给大家简单介绍一下:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
# 采集信息
from_addrs = input('请输入发件人的邮箱: ')
password = input('请输入发件人的 QQ 邮箱授权码: ')
to_addrs = []
while True:
a=input('请输入收件人邮箱:')
# 输入收件人邮箱
to_addrs.append(a)
# 写入列表
b=input('是否继续输入,n退出,任意键继续:')
# 询问是否继续输入
if b == 'n':
break
from email.header import Header
# 设置eamil信息
# 添加一个MIMEmultipart类,处理正文及附件
msg = MIMEMultipart()
msg['From'] = from_addrs
msg['To'] = Header(','.join(to_addrs))
msg['Subject'] = 'title'
# 推荐使用.html格式的正文内容,这样比较灵活,可以附加图片地址,调整格式等
with open('abc.html','r') as f:
content = f.read()
# 设置.html格式参数
part1 = MIMEText(content,'html','utf-8')
# 添加一个.txt文本附件
with open('abc.txt','r')as h:
content2 = h.read()
# 设置.txt参数
part2 = MIMEText(content2,'plain','utf-8')
# 附件设置内容类型,方便起见,设置为二进制流
part2['Content-Type'] = 'octet-stream'
# 设置附件头,添加文件名
part2['Content-Disposition'] = 'attachment;filename="abc.txt"'
# 添加照片附件
with open('1.png','rb')as fp:
picture = MIMEImage(fp.read())
# 与txt文件设置相似
picture['Content-Type'] = 'octet-stream'
picture['Content-Disposition'] = 'attachment;filename="1.png"'
# 将内容附加到邮件主体中
msg.attach(part1)
msg.attach(part2)
msg.attach(picture)
# 登录并发送
try:
server = smtplib.SMTP_SSL()
server.connect('smtp.qq.com', 465)
server.login(from_addrs,password)
server.sendmail(from_addrs, to_addrs, msg.as_string())
print('发送成功')
server.quit()
# 关闭服务器
except smtplib.SMTPException as e:
print('遇到错误', e)
这里讲述的过于简单,给大家推荐一篇大佬的文章,供大家学习:简单三步,用 Python 发邮件。今天讲的有点多,但很多都是了解性的知识,坚持看完的小伙伴还请给博主点个赞呗~