python之高级篇

  • 一、文件操作
  • 二、读写文本文件
  • 三、读写二进制文件
  • 四、读写JSON文件
  • 五、异常详解
  • 六、进程和线程
  • 七、单进程与多进程
  • 八、多线程编程
  • 九、多进程还是多线程
  • 十、requests 库
  • 十一、数据库操作

一、文件操作

  在实际开发中,常常需要对程序中的数据进行持久化操作,而实现数据持久化最直接简单的方式就是将数据保存到文件中。在Python中实现文件的读写操作其实非常简单,通过Python内置的open函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象,接下来就可以对文件进行读写操作了。这里所说的操作模式是指要打开什么样的文件(字符文件还是二进制文件)以及做什么样的操作(读、写还是追加),具体的如下表所示。

操作模式 具体含义
'r'           读取 (默认)
'w'           写入(会先截断之前的内容)
'x'           写入,如果文件已经存在会产生异常
'a'           追加,将内容写入到已有文件的末尾
'b'           二进制模式
't'           文本模式(默认)
'+'          更新(既可以读又可以写)

  通过encoding参数指定编码(如果不指定,默认值是None,那么在读取文件时使用的是操作系统默认的编码),如果不能保证保存文件时使用的编码方式与encoding参数指定的编码方式是一致的,那么就可能因无法解码字符而导致读取失败。

f = open('c://user.sql', 'r', encoding='utf-8')

二、读写文本文件

  读取文本文件时,需要在使用open函数时指定好带路径的文件名(可以使用相对路径或绝对路径)并将文件模式设置为’r’(如果不指定,默认值也是’r’),下面的例子演示了如何读取一个纯文本文件。

def main():f = open('c://user.sql', 'r', encoding='utf-8')print(f.read())f.close()
if __name__ == '__main__':main()

  请注意上面的代码,如果open函数指定的文件并不存在或者无法打开,那么将引发异常状况导致程序崩溃。为了让代码有一定的健壮性和容错性,我们可以使用Python的异常机制对可能在运行时发生状况的代码进行适当的处理,如下所示。

def main():f = Nonetry:f = open('c://user.sql', 'r', encoding='utf-8')print(f.read())except FileNotFoundError:print('无法打开指定的文件!')except LookupError:print('指定了未知的编码!')except UnicodeDecodeError:print('读取文件时解码错误!')finally:if f:f.close()
if __name__ == '__main__':main()

  在 Python 中,我们可以将那些在运行时可能会出现状况的代码放在 try 代码块中,在try代码块的后面可以跟上一个或多个except来捕获可能出现的异常状况。例如在上面读取文件的过程中,文件找不到会引发FileNotFoundError,指定了未知的编码会引发LookupError,而如果读取文件时无法按指定方式解码会引发UnicodeDecodeError,我们在try后面跟上了三个except分别处理这三种不同的异常状况。最后我们使用finally代码块来关闭打开的文件,释放掉程序中获取的外部资源,由于finally块的代码不论程序正常还是异常都会执行到,因此我们通常把finally块称为“总是执行代码块”,它最适合用来做释放外部资源的操作。

  除了使用文件对象的read方法读取文件之外,还可以使用for-in循环逐行读取或者用readlines方法将文件按行读取到一个列表容器中,代码如下所示。

import timedef main():# 通过for-in循环逐行读取f = open('c://user.sql', 'r', encoding='utf-8')for line in f:print(line, end='')time.sleep(0.5)print()# 读取文件按行读取到列表中f = open('c://user.sql', 'r', encoding='utf-8')lines = f.readlines()print(lines)f.close()if __name__ == '__main__':main()

  要将文本信息写入文件文件也非常简单,在使用 open 函数时指定好文件名并将文件模式设置为’w’即可。注意如果需要对文件内容进行追加式写入,应该将模式设置为’a’。如果要写入的文件不存在会自动创建文件而不是引发异常。

def main():# 写入f = open('c://aa.txt', 'w', encoding='utf-8')f.write("123456")f.close()# 追加f = open("c://aa.txt", 'a', encoding='utf-8')f.write("78910j")f.close()if __name__ == '__main__':main()

三、读写二进制文件

  知道了如何读写文本文件要读写二进制文件也就很简单了,下面的代码实现了复制图片文件的功能。

def main():fs1 = open('c://aa.png', 'rb')data = fs1.read()print(type(data))  # <class 'bytes'>fs2 = open('c://bb.png', 'wb')fs2.write(data)print('程序执行结束.')if __name__ == '__main__':main()

四、读写JSON文件

  如果希望把一个列表或者一个字典中的数据保存到文件中又该怎么做呢?答案是将数据以JSON格式进行保存。JSON是“JavaScript Object Notation”的缩写,它本来是JavaScript语言中创建对象的一种字面量语法,现在已经被广泛的应用于跨平台跨语言的数据交换,原因很简单,因为JSON也是纯文本,任何系统任何编程语言处理纯文本都是没有问题的。目前JSON基本上已经取代了XML作为异构系统间交换数据的事实标准。关于JSON的知识,更多的可以参考JSON的官方网站,从这个网站也可以了解到每种语言处理JSON数据格式可以使用的工具或三方库,下面是一个JSON的简单例子。

{"id":12,"name": "张三","age": 38,"friends": ["王大锤", "白元芳"],"role": {"id":2,"roleName":"超级管理员"}
}

我们使用Python中的json模块就可以将字典或列表以JSON格式保存到文件中,代码如下所示。

import jsondef main():data = {"id": 12,"name": "张三","age": 38,"friends": ["王大锤", "白元芳"],"role": {"id": 2,"roleName": "超级管理员"}}fs = open('data.json', 'w', encoding='utf-8')json.dump(data, fs)    print('保存数据完成!')if __name__ == '__main__':main()

json 模块主要有四个比较重要的函数,分别是:

  * dump - 将Python对象按照JSON格式序列化到文件中
  * dumps - 将Python对象处理成JSON格式的字符串
  * load - 将文件中的JSON数据反序列化成对象
  * loads - 将字符串的内容反序列化成Python对象

  这里出现了两个概念,一个叫序列化,一个叫反序列化。自由的百科全书维基百科上对这两个概念是这样解释的:“序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换为可以存储或传输的形式,这样在需要的时候能够恢复到原先的状态,而且通过序列化的数据重新获取字节时,可以利用这些字节来产生原始对象的副本(拷贝)。与这个过程相反的动作,即从一系列字节中提取数据结构的操作,就是反序列化(deserialization)”。

import jsondef main():fs = open('data.json', 'r', encoding='utf-8')data = json.load(fs)print(data)if __name__ == '__main__':main()

五、异常详解

  异常处理在任何一门编程语言里都是值得关注的一个话题,良好的异常处理可以让你的程序更加健壮,清晰的错误信息更能帮助你快速修复问题。在Python中,和不部分高级语言一样,使用了try/except/finally 语句块来处理异常,如果你有其他编程语言的经验,实践起来并不难。

  在可能发生异常的位置使用 try/except/finally 来控制程序出现异常后的操作,而不是程序崩溃并结束。

def main():f = Nonetry:f = open('致橡树.txt', 'r', encoding='utf-8')print(f.read())except FileNotFoundError:print('无法打开指定的文件!')except LookupError:print('指定了未知的编码!')except UnicodeDecodeError:print('读取文件时解码错误!')finally:if f:f.close()
if __name__ == '__main__':main()

  如果不愿意在 finally 代码块中关闭文件对象释放资源,也可以使用上下文语法,通过 with 关键字指定文件对象的上下文环境并在离开上下文环境时自动释放文件资源,代码如下所示。

def main():try:with open('致橡树.txt', 'r', encoding='utf-8') as f:print(f.read())except FileNotFoundError:print('无法打开指定的文件!')except LookupError:print('指定了未知的编码!')except UnicodeDecodeError:print('读取文件时解码错误!')
if __name__ == '__main__':main()

例如上面json文件读取的代码可以改写为:

import jsondef main():try:with open('data.json', 'r', encoding='utf-8') as fs:data = json.load(fs)print(data)except IOError as e:print(e)if __name__ == '__main__':main()

六、进程和线程

  今天我们使用的计算机早已进入多CPU或多核时代,而我们使用的操作系统都是支持“多任务”的操作系统,这使得我们可以同时运行多个程序,也可以将一个程序分解为若干个相对独立的子任务,让多个子任务并发的执行,从而缩短程序的执行时间,同时也让用户获得更好的体验。因此在当下不管是用什么编程语言进行开发,实现让程序同时执行多个任务也就是常说的“并发编程”,应该是程序员必备技能之一。为此,我们需要先讨论两个概念,一个叫进程,一个叫线程。

  进程就是操作系统中执行的一个程序,操作系统以进程为单位分配存储空间,每个进程都有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据,操作系统管理所有进程的执行,为它们合理的分配资源。进程可以通过fork或spawn的方式来创建新的进程来执行其他的任务,不过新的进程也有自己独立的内存空间,因此必须通过进程间通信机制(IPC,Inter-Process Communication)来实现数据共享,具体的方式包括管道、信号、套接字、共享内存区等。

  一个进程还可以拥有多个并发的执行线索,简单的说就是拥有多个可以获得CPU调度的执行单元,这就是所谓的线程。由于线程在同一个进程下,它们可以共享相同的上下文,因此相对于进程而言,线程间的信息共享和通信更加容易。当然在单核CPU系统中,真正的并发是不可能的,因为在某个时刻能够获得CPU的只有唯一的一个线程,多个线程共享了CPU的执行时间。使用多线程实现并发编程为程序带来的好处是不言而喻的,最主要的体现在提升程序的性能和改善用户体验,今天我们使用的软件几乎都用到了多线程技术,这一点可以利用系统自带的进程监控工具(如macOS中的“活动监视器”、Windows中的“任务管理器”)来证实,如下图所示。

  当然多线程也并不是没有坏处,站在其他进程的角度,多线程的程序对其他程序并不友好,因为它占用了更多的CPU执行时间,导致其他程序无法获得足够的CPU执行时间;另一方面,站在开发者的角度,编写和调试多线程的程序都对开发者有较高的要求,对于初学者来说更加困难。

  Python既支持多进程又支持多线程,因此使用Python实现并发编程主要有3种方式:多进程、多线程、多进程+多线程。

七、单进程与多进程

  下面用一个下载文件的例子来说明使用多进程和不使用多进程到底有什么差别,先看看下面的代码。

from random import randint
from time import time, sleepdef download_task(filename):print('开始下载%s...' % filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))def main():start = time()download_task('Python从入门到住院.pdf')download_task('Peking Hot.avi')end = time()print('总共耗费了%.2f秒.' % (end - start))if __name__ == '__main__':main()

  从上面的例子可以看出,如果程序中的代码只能按顺序一点点的往下执行,那么即使执行两个毫不相关的下载任务,也需要先等待一个文件下载完成后才能开始下一个下载任务,很显然这并不合理也没有效率。接下来我们使用多进程的方式将两个下载任务放到不同的进程中,代码如下所示。

from multiprocessing import Process
from os import getpid
from random import randint
from time import time, sleepdef download_task(filename):print('启动下载进程,进程号[%d].' % getpid())print('开始下载%s...' % filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))def main():start = time()p1 = Process(target=download_task, args=('Python从入门到住院.pdf',))p1.start()p2 = Process(target=download_task, args=('Peking Hot.avi',))p2.start()p1.join()p2.join()end = time()print('总共耗费了%.2f秒.' % (end - start))if __name__ == '__main__':main()

  在上面的代码中,我们通过Process类创建了进程对象,通过target参数我们传入一个函数来表示进程启动后要执行的代码,后面的args是一个元组,它代表了传递给函数的参数。Process对象的start方法用来启动进程,而join方法表示等待进程执行结束。运行上面的代码可以明显发现两个下载任务“同时”启动了,而且程序的执行时间将大大缩短,不再是两个任务的时间总和。

八、多线程编程

  在Python早期的版本中就引入了thread模块(现在名为_thread)来实现多线程编程,然而该模块过于底层,而且很多功能都没有提供,因此目前的多线程开发我们推荐使用threading模块,该模块对多线程编程提供了更好的面向对象的封装。我们把刚才下载文件的例子用多线程的方式来实现一遍。

from random import randint
from threading import Thread
from time import time, sleepdef download(filename):print('开始下载%s...' % filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))def main():start = time()t1 = Thread(target=download, args=('Python从入门到住院.pdf',))t1.start()t2 = Thread(target=download, args=('Peking Hot.avi',))t2.start()t1.join()t2.join()end = time()print('总共耗费了%.3f秒' % (end - start))if __name__ == '__main__':main()

  我们可以直接使用threading模块的Thread类来创建线程,但是我们之前讲过一个非常重要的概念叫“继承”,我们可以从已有的类创建新类,因此也可以通过继承Thread类的方式来创建自定义的线程类,然后再创建线程对象并启动线程。代码如下所示。

from random import randint
from threading import Thread
from time import time, sleepclass DownloadTask(Thread):def __init__(self, filename):super().__init__()self._filename = filenamedef run(self):print('开始下载%s...' % self._filename)time_to_download = randint(5, 10)sleep(time_to_download)print('%s下载完成! 耗费了%d秒' % (self._filename, time_to_download))def main():start = time()t1 = DownloadTask('Python从入门到住院.pdf')t1.start()t2 = DownloadTask('Peking Hot.avi')t2.start()t1.join()t2.join()end = time()print('总共耗费了%.2f秒.' % (end - start))if __name__ == '__main__':main()

  因为多个线程可以共享进程的内存空间,因此要实现多个线程间的通信相对简单,大家能想到的最直接的办法就是设置一个全局变量,多个线程共享这个全局变量即可。但是当多个线程共享同一个变量(我们通常称之为“资源”)的时候,很有可能产生不可控的结果从而导致程序失效甚至崩溃。如果一个资源被多个线程竞争使用,那么我们通常称之为“临界资源”,对“临界资源”的访问需要加上保护,否则资源会处于“混乱”的状态。下面的例子演示了100个线程向同一个银行账户转账(转入1元钱)的场景,在这个例子中,银行账户就是一个临界资源,在没有保护的情况下我们很有可能会得到错误的结果。

from time import sleep
from threading import Threadclass Account(object):def __init__(self):self._balance = 0def deposit(self, money):# 计算存款后的余额new_balance = self._balance + money# 模拟受理存款业务需要0.01秒的时间sleep(0.01)# 修改账户余额self._balance = new_balance@propertydef balance(self):return self._balanceclass AddMoneyThread(Thread):def __init__(self, account, money):super().__init__()self._account = accountself._money = moneydef run(self):self._account.deposit(self._money)def main():account = Account()threads = []# 创建100个存款的线程向同一个账户中存钱for _ in range(100):t = AddMoneyThread(account, 1)threads.append(t)t.start()# 等所有存款的线程都执行完毕for t in threads:t.join()print('账户余额为: ¥%d元' % account.balance)if __name__ == '__main__':main()

  运行上面的程序,结果让人大跌眼镜,100个线程分别向账户中转入1元钱,结果居然远远小于100元。之所以出现这种情况是因为我们没有对银行账户这个“临界资源”加以保护,多个线程同时向账户中存钱时,会一起执行到new_balance = self._balance + money这行代码,多个线程得到的账户余额都是初始状态下的0,所以都是0上面做了+1的操作,因此得到了错误的结果。在这种情况下,“锁”就可以派上用场了。我们可以通过“锁”来保护“临界资源”,只有获得“锁”的线程才能访问“临界资源”,而其他没有得到“锁”的线程只能被阻塞起来,直到获得“锁”的线程释放了“锁”,其他线程才有机会获得“锁”,进而访问被保护的“临界资源”。下面的代码演示了如何使用“锁”来保护对银行账户的操作,从而获得正确的结果。

from time import sleep
from threading import Thread, Lockclass Account(object):def __init__(self):self._balance = 0self._lock = Lock()def deposit(self, money):# 先获取锁才能执行后续的代码self._lock.acquire()try:new_balance = self._balance + moneysleep(0.01)self._balance = new_balancefinally:# 在finally中执行释放锁的操作保证正常异常锁都能释放self._lock.release()@propertydef balance(self):return self._balance
class AddMoneyThread(Thread):def __init__(self, account, money):super().__init__()self._account = accountself._money = moneydef run(self):self._account.deposit(self._money)
def main():account = Account()threads = []# 创建100个存款的线程向同一个账户中存钱for _ in range(100):t = AddMoneyThread(account, 1)threads.append(t)t.start()# 等所有存款的线程都执行完毕for t in threads:t.join()print('账户余额为: ¥%d元' % account.balance)
if __name__ == '__main__':main()

  比较遗憾的一件事情是Python的多线程并不能发挥CPU的多核特性,这一点只要启动几个执行死循环的线程就可以得到证实了。之所以如此,是因为Python的解释器有一个“全局解释器锁”(GIL)的东西,任何线程执行前必须先获得GIL锁,然后每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行,这是一个历史遗留问题,但是即便如此,就如我们之前举的例子,使用多线程在提升执行效率和改善用户体验方面仍然是有积极意义的。

九、多进程还是多线程

  无论是多进程还是多线程,只要数量一多,效率肯定上不去,为什么呢?我们打个比方,假设你不幸正在准备中考,每天晚上需要做语文、数学、英语、物理、化学这5科的作业,每项作业耗时1小时。如果你先花1小时做语文作业,做完了,再花1小时做数学作业,这样,依次全部做完,一共花5小时,这种方式称为单任务模型。如果你打算切换到多任务模型,可以先做1分钟语文,再切换到数学作业,做1分钟,再切换到英语,以此类推,只要切换速度足够快,这种方式就和单核CPU执行多任务是一样的了,以旁观者的角度来看,你就正在同时写5科作业。

  但是,切换作业是有代价的,比如从语文切到数学,要先收拾桌子上的语文书本、钢笔(这叫保存现场),然后,打开数学课本、找出圆规直尺(这叫准备新环境),才能开始做数学作业。操作系统在切换进程或者线程时也是一样的,它需要先保存当前执行的现场环境(CPU寄存器状态、内存页等),然后,把新任务的执行环境准备好(恢复上次的寄存器状态,切换内存页等),才能开始执行。这个切换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了,这种情况最常见的就是硬盘狂响,点窗口无反应,系统处于假死状态。所以,多任务一旦多到一个限度,反而会使得系统性能急剧下降,最终导致所有任务都做不好。

  是否采用多任务的第二个考虑是任务的类型,可以把任务分为计算密集型和I/O密集型。计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如对视频进行编码解码或者格式转换等等,这种任务全靠CPU的运算能力,虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低。计算密集型任务由于主要消耗CPU资源,这类任务用Python这样的脚本语言去执行效率通常很低,最能胜任这类任务的是C语言,我们之前提到了Python中有嵌入C/C++代码的机制。

  除了计算密集型任务,其他的涉及到网络、存储介质I/O的任务都可以视为I/O密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待I/O操作完成(因为I/O的速度远远低于CPU和内存的速度)。对于I/O密集型任务,如果启动多任务,就可以减少I/O等待时间从而让CPU高效率的运转。有一大类的任务都属于I/O密集型任务,这其中包括了我们很快会涉及到的网络应用和Web应用。

十、requests 库

  HTTP 是超文本传输协议(Hyper-Text Transfer Proctol)的简称,维基百科上对HTTP的解释是:超文本传输协议是一种用于分布式、协作式和超媒体信息系统的应用层协议,它是万维网数据通信的基础,设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法,通过HTTP或者HTTPS(超文本传输安全协议)请求的资源由URI(统一资源标识符)来标识。requests 是一个基于HTTP协议来使用网络的第三库,其官方网站有这样的一句介绍它的话:“Requests是唯一的一个非转基因的Python HTTP库,人类可以安全享用。”简单的说,使用requests库可以非常方便的使用HTTP,避免安全缺陷、冗余代码以及“重复发明轮子”。下面我们还是通过requests来实现一个访问网络数据接口并从中获取美女图片下载链接然后下载美女图片到本地的例子程序,程序中使用了天行数据提供的网络API。

  我们可以先通过pip安装requests及其依赖库。

pip install requests

然后通过 pip list 命令查看是否安装成功。

C:\Users\Administrator>pip list
Package    Version
---------- ---------
certifi    2020.12.5
chardet    4.0.0
idna       2.10
pip        21.0.1
requests   2.25.1
setuptools 47.1.0
urllib3    1.26.3

使用

from threading import Thread
import requests# 继承Thread类创建自定义的线程类
class DownloadHanlder(Thread):def __init__(self, url):super().__init__()self.url = urldef run(self):filename = self.url[self.url.rfind('/') + 1:]resp = requests.get(self.url)with open('c://' + filename, 'wb') as f:f.write(resp.content)
def main():# 通过requests模块的post函数获取网络json资源resp = requests.post('http://58.42.239.163:8888/jwxt/findPublicNoteBook')# 将服务器返回的JSON格式的数据解析为字典data_model = resp.json()print(data_model)for mm_dict in data_model['obj']:url = mm_dict['img']# 通过多线程的方式实现图片下载DownloadHanlder("http://58.42.239.163:8888/static/" + url).start()
if __name__ == '__main__':main()

十一、数据库操作

  在 Python 3中,我们通常使用纯 Python 的三方库 PyMySQL 来访问 MySQL 数据库,它应该是目前 Python 操作 MySQL 数据库最好的选择。使用 PyMySQL 前需要安装 PyMySQL,然后就可以使用 PyMySQL 进行数据库的增删改查操作。

pip install pymysql

数据准备:

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) NOT NULL,`password` varchar(50) NOT NULL,`telephone` varchar(11) NOT NULL,`email` varchar(50) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
insert  into `user`(`id`,`name`,`password`,`telephone`,`email`) values (1,'张三','123456','15902698148','123@qq.com');

添加数据:

import pymysqldef main():name = input('姓名: ')password = input('密码: ')telephone = input('电话: ')email = input('邮箱: ')# 1. 创建数据库连接对象con = pymysql.connect(host='localhost', port=3306,database='test-db', charset='utf8',user='root', password='123456')try:# 2. 通过连接对象获取游标with con.cursor() as cursor:# 3. 通过游标执行SQL并获得执行结果result = cursor.execute('insert into user(name,password,telephone,email) values (%s, %s, %s, %s)',(name, password, telephone, email))if result == 1:print('添加成功!')# 4. 操作成功提交事务con.commit()finally:# 5. 关闭连接释放资源con.close()if __name__ == '__main__':main()

修改数据:

  其实在大部分的编程语言中操作数据库都只有两类操作,及查询和更新。修改数据的操作和添加基本相同,删除也是类似的。

  注意:如果不希望每次 SQL 操作之后手动提交或回滚事务,可以像下面的代码那样,在创建连接的时候多加一个名为 autocommit 的参数并将它的值设置为 True,表示每次执行 SQL 之后自动提交。如果程序中不需要使用事务环境也不希望手动的提交或回滚就可以这么做。

import pymysqldef main():data_id = int(input('ID: '))name = input('姓名: ')password = input('密码: ')telephone = input('电话: ')email = input('邮箱: ')# 1. 创建数据库连接对象con = pymysql.connect(host='localhost', port=3306,database='test-db', charset='utf8',user='root', password='123456', autocommit=True)try:# 2. 通过连接对象获取游标with con.cursor() as cursor:# 3. 通过游标执行SQL并获得执行结果result = cursor.execute('update user set name =%s,password =%s,telephone =%s,email =%s where id =%s',(name, password, telephone, email, data_id))if result == 1:print('添加成功!')finally:# 5. 关闭连接释放资源con.close()if __name__ == '__main__':main()

查询数据:

  在 Python 中调用游标的 fetchall 即可获取全部的结果集合,集合中的每个元素都是标准的 json 对象。如果查询的结果确定为一条时使用 fetchone 会将结果封装成 json 对象。

import pymysql
from pymysql.cursors import DictCursordef main():# 1. 创建数据库连接对象con = pymysql.connect(host='localhost', port=3306,database='test-db', charset='utf8',user='root', password='123456')try:with con.cursor(cursor=DictCursor) as cursor:cursor.execute('select * from user')results = cursor.fetchall()print(results)print('id\tname\tpassword\ttelephone\temail')for dept in results:print(dept['id'], end='\t')print(dept['name'], end='\t')print(dept['password'], end='\t')print(dept['telephone'], end='\t')print(dept['email'])finally:con.close()if __name__ == '__main__':main()

python(三)之高级篇相关推荐

  1. 【Python教程】高级篇

    目录 3.1内置模块 3.1.1builtins模块 3.1.1.1输入输出函数 3.1.1.2类型转换函数 3.1.1.3统计相关函数 3.1.1.4进制转换函数 3.1.1.5编码相关函数 3.1 ...

  2. yield python3 知乎_运维学python之爬虫高级篇(七)scrapy爬取知乎关注用户存入mongodb...

    首先,祝大家开工大吉! 本篇将要介绍的是从一个用户开始,通过抓关注列表和粉丝列表,实现用户的详细信息抓取并将抓取到的结果存储到 MongoDB. 1 环境需求 基础环境沿用之前的环境,只是增加了Mon ...

  3. [python爬虫] Selenium高级篇之窗口移动、弹出对话框自登录

    在我们使用Selenium Python制作自动爬虫和网页自动测试的时候,通常会遇到弹出新的窗体或对话框的时候,此时你捕获的窗体已经被打断,从而干扰你的爬虫. 那怎么解决这个问题呢? 本篇文章主要记录 ...

  4. python win10 捕获 弹出窗口_[python爬虫] Selenium高级篇之窗口移动、弹出对话框自登录...

    在我们使用Selenium Python制作自动爬虫和网页自动测试的时候,通常会遇到弹出新的窗体或对话框的时候,此时你捕获的窗体已经被打断,从而干扰你的爬虫. 那怎么解决这个问题呢? 本篇文章主要记录 ...

  5. 搞定Python,Python书单高级篇

    关注微信公众号"资料在线",后台回复"礼物"."python新书单"有惊喜! 新年过后,开工已经一周了,你还记得许下的新年愿望吗?(点击查看 ...

  6. SpringCloud—笔记(三)高级篇

    SpringCloud Alibaba 入门简介 1.why会出现SpringCloud alibaba Spring Cloud Netflix项目进入维护模式 进入维护模式意味着 Spring C ...

  7. 人工智能(10)---机器学习知识体系篇(初级篇,中级篇,高级篇)

    机器学习知识体系篇(初级篇,中级篇,高级篇) 下面是自己总结一套人工智能机器学习整个知识体系,一起学习,有总结不到位的希望大家给出纠正! 一 人工智能基础语法篇 二 人工智能中级篇 三 人工智能高级篇

  8. python学习高级篇(part10)--类对象的特殊方法和特殊属性

    学习笔记,仅供参考,有错必纠 文章目录 python 学习高级篇 类对象的特殊方法之`__del__()` 类对象的特殊方法之`__getattr__()` 类对象的特殊方法之`__getitem__ ...

  9. 『高级篇』docker容器来说什么是微服务(三)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『高级篇』docker容器来说什么是微服务(三) 上一节说了单体架构,单体架构也无法适应我们的服务,来说说微服务,看能否解决单 ...

最新文章

  1. Redis数据库简介与(CentOS 7)编译安装
  2. docker run -it 如何退出_Docker学习笔记(4)容器的基本命令 1 - 你个小秃头
  3. 《面向对象程序设计》第11章在线测试
  4. libsvm与python的使用
  5. 利用linux的df和du命令查看文件和目录的内存占用
  6. Ubuntu一键安装LAMP环境
  7. 【STC15库函数上手笔记】2、GPIO
  8. TIM怎么设置禁止窗口抖动 TIM防抖设置技巧
  9. Redis分布式锁如何提高可用性
  10. 与内存管理相关的几个宏
  11. 关于html语义化 以下哪个说法是正确呢,前端面试题2019年网易工程师面试题及答案解析...
  12. javascript日期格式化 转换
  13. 【python自动化第十篇:】
  14. 城市轨道交通运营管理属于什么院系_城市轨道交通运营管理专业
  15. Openvpn搭建并使用用户名密码登录
  16. windows聚焦壁纸不更新_Win10无法自动更换聚焦锁屏壁纸怎么办?
  17. 曾被疑为有血缘关系的明星
  18. Access数据库常用函数大全
  19. Java调用ffmepg+mencoder视频格式转换
  20. 解决苹果手机绑定小米手环4支付宝,蓝牙无法连接问题。

热门文章

  1. 【概念】为什么区块链被称为分布式数据库?举例讲解分布式数据库包会教程。区块链分布式数据库到底是什么?什么是分布式数据库?一千六百字讲清楚什么事分布式数据库。
  2. express如何返回一个html文档,node.js express 返回一个静态页面
  3. Linux学习笔记--locate命令(文件搜索命令)
  4. 移动硬盘加密!让windows用户无法查看移动硬盘!
  5. mysql tokudb innodb_TokuDB vs Innodb 基准测试对比
  6. Win11 桌面快捷方式未全部显示的诡异现象及解决方法
  7. 1.银行中的等额本金C程序
  8. [资讯] NFC有什么作用。小米手机3NFC解读
  9. Android_控制闪光灯
  10. SpringBoot的Web开发入门案例3—异常处理