后端编程Python3-数据库编程

栏目:资讯发布:2023-11-06浏览:3收藏

后端编程Python3-数据库编程,第1张

对大多数软件开发者而言,术语数据库通常是指RDBMS(关系数据库管理系统), 这些系统使用表格(类似于电子表格的网格),其中行表示记录,列表示记录的字段。表格及其中存放的数据是使用SQL (结构化査询语言)编写的语句来创建并操纵的。Python提供了用于操纵SQL数据库的API(应用程序接口),通常与作为标准的SQLite 3数据库一起发布。

另一种数据库是DBM (数据库管理器),其中存放任意数量的键-值项。Python 的标准库提供了几种DBM的接口,包括某些特定于UNIX平台的。DBM的工作方式 与Python中的字典类似,区别在于DBM通常存放于磁盘上而不是内存中,并且其键与值总是bytes对象,并可能受到长度限制。本章第一节中讲解的shelve模块提供了方便的DBM接口,允许我们使用字符串作为键,使用任意(picklable)对象作为值。

如果可用的 DBM 与 SQLite 数据库不够充分,Python Package Index, pypipythonorg/pypi中提供了大量数据库相关的包,包括bsddb DBM ("Berkeley DB"),对象-关系映射器,比如SQLAlchemy (wwwsqlalchemyorg),以及流行的客户端/服务器数据的接口,比如 DB2、Informix、Ingres、MySQL、ODBC 以及 PostgreSQL。

本章中,我们将实现某程序的两个版本,该程序用于维护一个DVD列表,并追踪每个DVD的标题、发行年份、时间长度以及发行者。该程序的第一版使用DBM (通过shelve模块)存放其数据,第二版则使用SQLite数据库。两个程序都可以加载与保存简单的XML格式,这使得从某个程序导出DVD数据并将其导入到其他程序成为可能。与DBM版相比,基于SQL的程序提供了更多一些的功能,并且其数据设计也稍干净一些。

121 DBM数据库

shelve模块为DBM提供了一个wrapper,借助于此,我们在与DBM交互时,可以将其看做一个字典,这里是假定我们只使用字符串键与picklable值,实际处理时, shelve模块会将键与值转换为bytes对象(或者反过来)。

由于shelve模块使用的是底层的DBM,因此,如果其他计算机上没有同样的DBM,那么在某台计算机上保存的DBM文件在其他机器上无法读取是可能的。为解决这一问题,常见的解决方案是对那些必须在机器之间可传输的文件提供XML导入与导出功能,这也是我们在本节的DVD程序dvds-dbmpy中所做的。

对键,我们使用DVD的标题;对值,则使用元组,其中存放发行者、发行年份以及时间。借助于shelve模块,我们不需要进行任何数据转换,并可以把DBM对象当做一个字典进行处理。

程序在结构上类似于我们前面看到的那种菜单驱动型的程序,因此,这里主要展示的是与DBM程序设计相关的那部分。下面给出的是程序main()函数中的一部分, 忽略了其中菜单处理的部分代码。

db = None

try:

db = shelveopen(filename, protocol=pickleHIGHEST_PROTOCOL)

finally:

if db is not None:

dbdose()

这里我们已打开(如果不存在就创建)指定的DBM文件,以便于对其进行读写操作。每一项的值使用指定的pickle协议保存为一个pickle,现有的项可以被读取, 即便是使用更底层的协议保存的,因为Python可以计算出用于读取pickle的正确协议。最后,DBM被关闭——其作用是清除DBM的内部缓存,并确保磁盘文件可以反映出已作的任何改变,此外,文件也需要关闭。

该程序提供了用于添加、编辑、列出、移除、导入、导出DVD数据的相应选项。除添加外,我们将忽略大部分用户接口代码,同样是因为已经在其他上下文中进行了展示。

def add_dvd(db):

title = Consoleget_string("Title", "title")

if not title:

return

director = Consoleget_string("Director", "director")

if not director:

return

year = Consoleget_integer("Year", "year",minimum=1896,

maximum=datetime,datetoday()year)

duration = Consoleget_integer("Duration (minutes)", "minutes“, minimum=0, maximum=6048)

db[title] = (director, year, duration)

dbsync()

像程序菜单调用的所有函数一样,这一函数也以DBM对象(db)作为其唯一参数。该函数的大部分工作都是获取DVD的详细资料,在倒数第二行,我们将键-值项存储在DBM文件中,DVD的标题作为键,发行者、年份以及时间(由shelve模块pickled在一起)作为值。

为与Python通常的一致性同步,DBM提供了与字典一样的API,因此,除了 shelveopen() 函数(前面已展示)与shelveShelfsync()方法(该方法用于清除shelve的内部缓存,并对磁盘上文件的数据与所做的改变进行同步——这里就是添加一个新项),我们不需要学习任何新语法。

def edit_dvd(db):

old_title = find_dvd(db, "edit")

if old_title is None:

return

title = Consolegetstring("Title", "title", old_title)

if not title:

return

director, year, duration = db[old_title]

db[title]= (director, year, duration)

if title != old_title:

del db[old_title]

dbsync()

为对某个DVD进行编辑,用户必须首先选择要操作的DVD,也就是获取DVD 的标题,因为标题用作键,值则用于存放其他相关数据。由于必要的功能在其他场合 (比如移除DVD)也需要使用,因此我们将其实现在一个单独的find_dvd()函数中,稍后将査看该函数。如果找到了该DVD,我们就获取用户所做的改变,并使用现有值作为默认值,以便提高交互的速度。(对于这一函数,我们忽略了大部分用户接口代码, 因为其与添加DVD时几乎是相同的。)最后,我们保存数据,就像添加时所做的一样。如果标题未作改变,就重写相关联的值;如果标题已改变,就创建一个新的键-值对, 并且需要删除原始项。

def find_dvd(db, message):

message = "(Start of) title to " + message

while True:

matches =[]

start = Consoleget_string(message, "title")

if not start:

return None

for title in db:

if titlelower()startswith(startlower()):

matchesappend(title)

if len(matches) == 0:

print("There are no dvds starting with", start)

continue

elif len(matches) == 1:

return matches[0]

elif len(matches) > DISPLAY_LIMIT:

print("Too many dvds start with {0}; try entering more of the title"format(start)

continue

else:

matches = sorted(matches, key=strlower)

for i, match in enumerate(matches):

print("{0}: {1}"format(i+1, match))

which = Consoleget_integer("Number (or 0 to cancel)",

"number", minimum=1, maximum=len(matches))

return matches[which - 1] if which != 0 else None

为尽可能快而容易地发现某个DVD,我们需要用户只输入其标题的一个或头几个字符。在具备了标题的起始字符后,我们在DBM中迭代并创建一个匹配列表。如果只有一个匹配项,就返回该项;如果有几个匹配项(但少于DISPLAY_LIMIT, 一个在程序中其他地方设置的整数),就以大小写不敏感的顺序展示所有这些匹配项,并为每一项设置一个编号,以便用户可以只输入编号就可以选择某个标题。(Consoleget_integer()函数可以接受0,即便最小值大于0,以便0可以用作一个删除值。通过使用参数allow_zero=False, 可以禁止这种行为。我们不能使用Enter键,也就是说,没有什么意味着取消,因为什么也不输入意味着接受默认值。)

def list_dvds(db):

start =”"

if len(db)> DISPLAYLIMIT:

start = Consoleget_string(“List those starting with [Enter=all]”, "start”)

print()

for title in sorted(db, key=strlower):

if not start or titleIower()startswith(startlower()):

director, year, duration = db[title]

print("{title} ({year}) {duration} minute{0}, by "

"{director}"format(Utils(duration),locals()))

列出所有DVD (或者那些标题以某个子字符串引导)就是对DBM的所有项进行迭代。

Utils()函数就是简单的s = lambda x: "" if x == 1 else "s",因此,如果时间长度不是1分钟,就返回"s"。

def remove_dvd(db):

title = find_dvd(db, "remove")

if title is None:

return

ans = Consoleget_bool("Remove {0}"format(title), "no")

if ans:

del db[title]

dbsync()

要移除一个DVD,首先需要找到用户要移除的DVD,并请求确认,获取后从DBM中删除该项即可。

到这里,我们展示了如何使用shelve模块打开(或创建)一个DBM文件,以及如何向其中添加项、编辑项、对其项进行迭代以及移除某个项。

遗憾的是,在我们的数据设计中存在一个瑕疵。发行者名称是重复的,这很容易导致不一致性,比如,发行者Danny DeVito可能被输入为"Danny De Vito",用于 一个**;也可以输入为“Danny deVito",用于另一个。为解决这一问题,可以使用两个DBM文件,主DVD文件使用标题键与(年份,时间长度,发行者ID)值; 发行者文件使用发行者ID (整数)键与发行者名称值。下一节展示的SQL数据库 版程序将避免这一瑕疵,这是通过使用两个表格实现的,一个用于DVD,另一个用于发行者。

122 SQL数据库

大多数流行的SQL数据库的接口在第三方模块中是可用的,Python带有sqlite3 模块(以及SQLite 3数据库),因此,在Python中,可以直接开始数据库程序设计。SQLite是一个轻量级的SQL数据库,缺少很多诸如PostgreSQL这种数据库的功能, 但非常便于构造原型系统,并且在很多情况下也是够用的。

为使后台数据库之间的切换尽可能容易,PEP 249 (Python Database API Specification v20)提供了称为DB-API 20的API规范。数据库接口应该遵循这一规范,比如sqlite3模块就遵循这一规范,但不是所有第三方模块都遵循。API规范中指定了两种主要的对象,即连接对象与游标对象。表12-1与表12-2中分别列出了这两种对象必须支持的API。在sqlite3模块中,除DB-API 20规范必需的之外,其连接对象与游标对象都提供了很多附加的属性与方法。

DVD程序的SQL版本为dvdssqlpy,该程序将发行者与DVD数据分开存储,以 避免重复,并提供一个新菜单,以供用户列出发行者。该程序使用的两个表格在图12-1

def connect(filename):

create= not ospathexists(filename)

db = sqlite3connect(filename)

if create:

cursor = dbcursor()

cursorexecute("CREATE TABLE directors ("

"id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "

"name TEXT UNIQUE NOT NULL)")

cursorexecute("CREATE TABLE dvds ("

"id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "

"title TEXT NOT NULL, "

"year INTEGER NOT NULL,"

"duration INTEGER NOT NULL, "

"director_id INTEGER NOT NULL, ”

"FOREIGN KEY (director_id) REFERENCES directors)")

dbcommit()

return db

sqlite3connect()函数会返回一个数据库对象,并打开其指定的数据库文件。如果该文件不存在,就创建一个空的数据库文件。鉴于此,在调用sqlite3connect()之前,我们要注意数据库是否是准备从头开始创建,如果是,就必须创建该程序要使用的表格。所有査询都是通过一个数据库游标完成的,可以从数据库对象的cursor()方法获取。

注意,两个表格都是使用一个ID字段创建的,ID字段有一个AUTOINCREMENT 约束——这意味着SQLite会自动为ID字段赋予唯一性的数值,因此,在插入新记录时,我们可以将这些字段留给SQLite处理。

SQLite支持有限的数据类型——实际上就是布尔型、数值型与字符串——但使用数据'‘适配器”可以对其进行扩展,或者是扩展到预定义的数据类型(比如那些用于日期与datetimes的类型),或者是用于表示任意数据类型的自定义类型。DVD程序并不需要这一功能,如果需要,sqlite3模块的文档提供了很多详细解释。我们使用的外部键语法可能与用于其他数据库的语法不同,并且在任何情况下,只是记录我们的意图,因为SQLite不像很多其他数据库那样需要强制关系完整性,sqlite3另一点与众不同的地方在于其默认行为是支持隐式的事务处理,因此,没有提供显式的“开始事务” 方法。

def add_dvd(db):

title = Consoleget_string("Title", "title")

if not title:

return

director = Consoleget_string("Director", "director")

if not director:

return

year = Consoleget_integer("Year", "year”, minimum=1896,

maximum=datetimedatetoday()year)

duration = Consoleget_integer("Duration (minutes)", "minutes",

minimum=0,maximum=6048)

director_id = get_and_set_director(db, director)

cursor = dbcursor()

cursorexecute("INSERT INTO dvds ”

"(title, year, duration, director_id)"

"VALUES (, , , )",

(title, year, duration, director_id))

dbcommit()

这一函数的开始代码与dvds-dbmpy程序中的对应函数一样,但在完成数据的收集后,与原来的函数有很大的差别。用户输入的发行者可能在也可能不在directors表格中,因此,我们有一个get_and_set_director()函数,在数据库中尚无某个发行者时, 该函数就将其插入到其中,无论哪种情况都返回就绪的发行者ID,以便在需要的时候插入到dvds表。在所有数据都可用后,我们执行一条SQL INSERT语句。我们不需要指定记录ID,因为SQLite会自动为我们提供。

在査询中,我们使用问号(?)作为占位符,每个都由包含SQL语句的字符串后面的序列中的值替代。命名的占位符也可以使用,后面在编辑记录时我们将看到。尽管避免使用占位符(而只是简单地使用嵌入到其中的数据来格式化SQL字符串)也是可能的,我们建议总是使用占位符,并将数据项正确编码与转义的工作留给数据库模块来完成。使用占位符的另一个好处是可以提高安全性,因为这可以防止任意的SQL 被恶意地插入到一个査询中。

def get_and_set_director(db, director):

director_id = get_director_id(db, director)

if directorjd is not None:

return director_id

cursor = dbcursor()

cursorexecute("lNSERT INTO directors (name) VALUES ()”,(director,))

dbcommit()

return get_director_id(db, director)

这一函数返回给定发行者的ID,并在必要的时候插入新的发行者记录。如果某个记录被插入,我们首先尝试使用get_director_id()函数取回其ID。

def get_director_id(db, director):

cursor = dbcursor()

cursorexecute("SELECT id FROM directors WHERE name=",(director,))

fields = cursorfetchone()

return fields[0] if fields is not None else None

get_director_id()函数返回给定发行者的ID,如果数据库中没有指定的发行者,就返回None。我们使用fetchone()方法,因为或者有一个匹配的记录,或者没有。(我们知道,不会有重复的发行者,因为directors表格的名称字段有一个UNIQUE约束,在任何情况下,在添加一个新的发行者之前,我们总是先检査其是否存在。)这种取回方法总是返回一个字段序列(如果没有更多的记录,就返回None)。即便如此,这里我们只是请求返回一个单独的字段。

def edit_dvd(db):

title, identity = find_dvd(db, "edit")

if title is None:

return

title = Consoleget_string("Title","title", title)

if not title:

return

cursor = dbcursor()

cursorexecute("SELECT dvdsyear, dvdsduration, directorsname"

“FROM dvds, directors "

"WHERE dvdsdirector_id = directorsid AND "

"dvdsid=:id", dict(id=identity))

year, duration, director = cursorfetchone()

director = Consoleget_string("Director", "director", director)

if not director:

return

year = Console,get_integer("Year","year", year, 1896,datetimedatetoday()year)

duration = Consoleget_integer("Duration (minutes)", "minutes",

duration, minimum=0, maximum=6048)

director_id = get_and_set_director(db, director)

cursorexecute("UPDATE dvds SET title=:title, year=:year,"

"duration=:duration, director_id=:directorjd "

"WHERE id=:identity", locals())

dbcommit()

要编辑DVD记录,我们必须首先找到用户需要操纵的记录。如果找到了某个记录,我们就给用户修改其标题的机会,之后取回该记录的其他字段,以便将现有值作为默认值,将用户的输入工作最小化,用户只需要按Enter键就可以接受默认值。这里,我们使用了命名的占位符(形式为:name),并且必须使用映射来提供相应的值。对SELECT语句,我们使用一个新创建的字典;对UPDATE语句,我们使用的是由 locals()返回的字典。

我们可以同时为这两个语句都使用新字典,这种情况下,对UPDATE语句,我们可以传递 dict(title=title, year=year, duration=duration, director_id=director_id, id=identity)),而非 locals()。

在具备所有字段并且用户已经输入了需要做的改变之后,我们取回相应的发行者ID (如果必要就插入新的发行者记录),之后使用新数据对数据库进行更新。我们采用了一种简化的方法,对记录的所有字段进行更新,而不仅仅是那些做了修改的字段。

在使用DBM文件时,DVD标题被用作键,因此,如果标题进行了修改,我们就需要创建一个新的键-值项,并删除原始项。不过,这里每个DVD记录都有一个唯一性的ID,该ID是记录初次插入时创建的,因此,我们只需要改变任何其他字段的值, 而不需要其他操作。

def find_dvd(db, message):

message = "(Start of) title to " + message

cursor = dbcursor()

while True:

start = Consoleget_stnng(message, "title")

if not start:

return (None, None)

cursorexecute("SELECT title, id FROM dvds "

"WHERE title LIKE ORDER BY title”,

(start +"%",))

records = cursorfetchall()

if len(records) == 0:

print("There are no dvds starting with", start)

continue

elif len(records) == 1:

return records[0]

elif len(records) > DISPLAY_LIMIT:

print("Too many dvds ({0}) start with {1}; try entering "

"more of the title"format(len(records),start))

continue

else:

for i, record in enumerate(records):

print("{0}:{1}"format(i + 1, record[0]))

which = Consoleget_integer("Number (or 0 to cancel)",

"number", minimum=1, maximum=len(records))

return records[which -1] if which != 0 else (None, None)

这一函数的功能与dvdsdbmpy程序中的find_dvd()函数相同,并返回一个二元组 (DVD标题,DVD ID)或(None, None),具体依赖于是否找到了某个记录。这里并不需要在所有数据上进行迭代,而是使用SQL通配符(%),因此只取回相关的记录。

由于我们希望匹配的记录数较小,因此我们一次性将其都取回到序列的序列中。如果有不止一个匹配的记录,但数量上又少到可以显示,我们就打印记录,并将每条记录附带一个数字编号,以便用户可以选择需要的记录,其方式与在dvds-dbmpy程序中所做的类似:

def list_dvds(db):

cursor = dbcursor()

sql = ("SELECT dvdstitle, dvdsyear, dvdsduration, "

"directorsname FROM dvds, directors "

"WHERE dvdsdirector_id = directorsid")

start = None

if dvd_count(db) > DISPLAY_LIMIT:

start = Consoleget_string("List those starting with [Enter=all]", "start")

sql += " AND dvdstitle LIKE "

sql += ” ORDER BY dvdstitle"

print()

if start is None:

cursorexecute(sql)

else:

cursorexecute(sql, (start +"%",))

for record in cursor:

print("{0[0]} ({0[1]}) {0[2]} minutes, by {0[3]}"format(record))

要列出每个DVD的详细资料,我们执行一个SELECT査询。该査询连接两个表,如果记录(由dvd_count()函数返回)数量超过了显示限制值,就将第2个元素添加到WHERE 分支,之后执行该査询,并在结果上进行迭代。每个记录都是一个序列,其字段是与 SELECT査询相匹配的。

def dvd_count(db):

cursor = dbcursor()

cursorexecute("SELECT COUNT() FROM dvds")

return cursorfetchone()[0]

我们将这几行代码放置在一个单独的函数中,因为我们在几个不同的函数中都需要使用这几行代码。

我们忽略了 list_directors()函数的代码,因为该函数在结构上与list_dvds()函数非常类似,只不过更简单一些,因为本函数只列出一个字段(name)。

def remove_dvd(db):

title, identity = find_dvd(db, "remove")

if title is None:

return

ans = Consoleget_bool("Remove {0}"format(title), "no")

if ans:

cursor = dbcursor()

cursorexecute("DELETE FROM dvds WHERE id=", (identity,))

dbcommit()

在用户需要删除一个记录时,将调用本函数,并且本函数与dvds-dbmpy程序中 相应的函数是非常类似的。

到此,我们完全查阅了 dvds-sqlpy程序,并且了解了如何创建数据库表格、选取 记录、在选定的记录上进行迭代以及插入、更新与删除记录。使用execute()方法,我们可以执行底层数据库所支持的任意SQL语句。

SQLite提供了比我们这里使用的多得多的功能,包括自动提交模式(以及任意其他类型的事务控制),以及创建可以在SQL查询内执行的函数的能力。提供一个工厂函数并用于控制对每个取回的记录返回什么(比如,一个字典或自定义类型,而不是字段序列)也是可能的。此外,通过传递“:memory:”作为文件名,创建内存中的SQLite 数据库也是可能的。

以上内容部分摘自视频课程05后端编程Python22 数据库编程,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

Django- 一个开放源代码的 Web 应用框架,由 Python 写成,采用了 MVC 的软件设计模式;

rpyc- 一个 Python 实现的 RPC 和分布式计算的工具。支持同步和异步操作、回调等;

saltstack 、 ansible 、 func - 基本 Python 开发的自动化配置管理与流程控制组件;

Mysql- 是一个非常流行的关系型数据库管理系统。

二、平台架构设计

1、 OMServer 架构图

大家对这个架构应该不会感到陌生,三层结构也是目前主流的运营平台架构。

2、 架构说明

OMServer 平台为三层架构,分别为 WEB 交互层、分布式计算层、集群管理服务层。

1) 、第一层:即为 WEB 交互层,典型的 B/S 架构,以供管理员操作的交互平台,也是 OMServer 的核心,基于 Django 开发;

2) 、第二层:分布式计算层,提供与主控端的连接通道,采用的是 rpyc 传输协议,协议操作流程:前端模块参数 -> 加密传输 -> 任务执行 -> 返回结果集 -> 解密输出。

3) 、第三层:集群管理服务层,整合 Python 主流的远程操作组件(支持 Saltstack 、 Anaible、 Func ),对被控端(业务服务器集群)进行管理,其中主控端可以根据不同 IDC 环境,采用多地多点的管理方式,可提升冗余度及执行效率。主控端操作模块以不同 Python 文件加以区分,便于维护,可灵活定制操作逻辑及横向扩展等特点。

# -- coding: cp936 --

class StuInfo:

def __init__(self):

selfStu=[{"Sno":"1","Sname":"姓名","ChineseScore":64,"MathsScore":34,"EnglishScore":94,"ComputerScore":83},

{"Sno":"2","Sname":"姓名","ChineseScore":44,"MathsScore":24,"EnglishScore":44,"ComputerScore":71},

{"Sno":"3","Sname":"姓名","ChineseScore":74,"MathsScore":35,"EnglishScore":74,"ComputerScore":93},

{"Sno":"4","Sname":"姓名","ChineseScore":94,"MathsScore":54,"EnglishScore":24,"ComputerScore":73}]

selfattribute={"Sno":"学号",

"Sname":"姓名",

"ChineseScore":"语文成绩",

"MathsScore":"数学成绩",

"EnglishScore":"英语成绩",

"ComputerScore":"计算机成绩"

}

def _add(self):

'''添加'''

singleInfo={}

for i in selfattribute:

if "Score" in i:

singleInfo[i]=int(raw_input(selfattribute[i]+"\n"))

else:

singleInfo[i]=raw_input(selfattribute[i]+"\n")strip()

selfStuappend(singleInfo)

print "添加成功OK"

for i in singleInfo:

print i,"=",singleInfo[i]

def _del(self):

"""删除学号为Sno的记录"""

Sno=raw_input("学号:\n")

selfSturemove(self__getInfo(Sno))

print "删除成功OK"

def _update(self):

"""更新数据"""

Sno=raw_input("学号\n")strip()

prefix="修改"

updateOperate={"1":"ChineseScore",

"2":"MathsScore",

"3":"EnglishScore",

"4":"ComputerScore"}

for i in updateOperate:

print i,"-->",prefix+selfattribute[updateOperate[i]]

getOperateNum=raw_input("选择操作:\n")

if getOperateNum:

getNewValue=int(raw_input("输入新的值:\n"))

record=self__getInfo(Sno)

record[updateOperate[getOperateNum]]=getNewValue

print "修改"+record["Sname"]+"的"+str(updateOperate[getOperateNum])+"成绩=",getNewValue,"\n成功OK"

def _getInfo(self):

"""查询数据"""

while True:

print "1->学号查询 2->条件查询 3->退出"

getNum=raw_input("选择:\n")

if getNum=="1":

Sno=raw_input("学号:\n")

print filter(lambda record:record["Sno"]==Sno,selfStu)[0]

elif getNum=="2":

print "ChineseScore 语文成绩;","MathsScore 数学成绩;","EnglishScore 英语成绩;","ComputerScore 计算机成绩;"

print "等于 ==,小于 <, 大于 > ,大于等于 >=,小于等于<= ,不等于!="

print "按如下格式输入查询条件 eg: ChineseScore>=60 "

expr=raw_input("条件:\n")

笭工蒂继郦荒垫维叮哩 Infos=self__getInfo(expr=expr)

if Infos:

print "共%d记录"%len(Infos)

for i in Infos:

print i

else:

print "记录为空"

elif getNum=="3":

break

else:

pass

def __getInfo(self,Sno=None,expr=""):

"""查询数据

根据学号 _getInfo("111111")

根据分数 _getInfo("EnglishSorce>80")"""

if Sno:

return filter(lambda record:record["Sno"]==Sno,selfStu)[0]

for operate in [">=",">","<=","<","==","!="]:

if operate in expr:

gradeName,value=exprsplit(operate)

return filter(lambda record: eval( repr(record[gradeNamestrip()])+operate+valuestrip()) ,selfStu)

return {}

def _showAll(self):

"""显示所有记录"""

for i in selfStu:

print i

@staticmethod

def test():

"""测试"""

_StuInfo=StuInfo()

while True:

print "1->录入数据 2->修改数据 3->删除数据 4->查询数据 5->查看数据 6->退出"

t=raw_input("选择:\n")

if t=="1":

print "录入数据"

_StuInfo_add()

elif t=="2":

print "修改数据"

_StuInfo_update()

elif t=="3":

print "删除数据"

_StuInfo_del()

elif t=="4":

print "查询数据"

_StuInfo_getInfo()

elif t=="5":

print "显示所有记录"

_StuInfo_showAll()

elif t=="6":

break

else:

pass

if __name__=="__main__":

StuInfotest()

1、批量导入Excel数据,批量导出到Excel。

2、首页实时显示物资在库状态,比如出库了哪些、数量、出库时间、借用人是谁(后期可能加入出库签名3、功能,再说)。可以选择不同显示方式:表格、图表等。

4、登录功能,设置几个管理员,可以控制操作权限等。

5、在线打印(可自动排版)或导出打印。

  简单网络管理协议SNMP(Simple Network Management Protocol)用于网络设备的管理。SNMP作为广泛应用于TCP/IP网络的网络管理标准协议,提供了统一的接口,从而实现了不同种类和厂商的网络设备之间的统一管理。

  SNMP协议分为三个版本:SNMPv1、SNMPv2c和SNMPv3。

  SNMP系统由网络管理系统NMS(Network Management System)、SNMP Agent、被管对象Management object和管理信息库MIB(Management Information Base)四部分组成。

  SNMP查询是指NMS主动向SNMP Agent发送查询请求,如图1-3所示。SNMP Agent接收到查询请求后,通过MIB表完成相应指令,并将结果反馈给NMS。SNMP查询操作有三种:Get、GetNext和GetBulk。SNMPv1版本不支持GetBulk操作。

  不同版本的SNMP查询操作的工作原理基本一致,唯一的区别是SNMPv3版本增加了身份验证和加密处理。下面以SNMPv2c版本的Get操作为例介绍SNMP查询操作的工作原理。假定NMS想要获取被管理设备MIB节点sysContact的值,使用可读团体名为public,过程如下所示:

  SNMP设置是指NMS主动向SNMP Agent发送对设备进行Set操作的请求,如下图示。SNMP Agent接收到Set请求后,通过MIB表完成相应指令,并将结果反馈给NMS。

  不同版本的SNMP Set操作的工作原理基本一致,唯一的区别是SNMPv3版本增加了身份验证和加密处理。下面以SNMPv3版本的Set操作为例介绍SNMP Set操作的工作原理。

假定NMS想要设置被管理设备MIB节点sysName的值为HUAWEI,过程如下所示:

  SNMPv1和SNMPv2c的Set操作报文格式如下图所示。一般情况下,SNMPv3的Set操作信息是经过加密封装在SNMP PDU中,其格式与SNMPv2c的Set操作报文格式一致。

  SNMP Traps是指SNMP Agent主动将设备产生的告警或事件上报给NMS,以便网络管理员及时了解设备当前运行的状态。

  SNMP Agent上报SNMP Traps有两种方式:Trap和Inform。SNMPv1版本不支持Inform。Trap和Inform的区别在于,SNMP Agent通过Inform向NMS发送告警或事件后,NMS需要回复InformResponse进行确认。

  在Ensp中搭建网络环境,在R2上启用SNMP作为SNMP agent,Linux主机作为NMS;为方便观察SNMP报文格式,在R2使用SNMP的版本为v2c。

通过下面的Python脚本获取R2的系统信息与当前的主机名

运行结果如下

  在R2接口上抓包结果如下,Linux主机向R2的161端口发送SNMP get-request报文,可以看到SNMP使用的版本为v2c,设置的团体名为public,随机生成了一个request-id,变量绑定列表(Variable bindings),即要查询的OID,但Value为空;值得注意的是这些信息都是明文传输的,为了安全在实际环境中应使用SNMPv3。

通过下面的Python脚本获取R2的接口信息。

运行结果如下:

在R2接口抓包结果如下,getBuikRequest相比get-request设置了一个max-repetitions字段,表明最多执行get操作的次数。Variable bindings中请求的OID条目只有一条。

下面Python脚本用于设置R2的主机名为SNMPv2R2。

运行结果如下

在路由器上可以看到主机名有R2变为了SNMPv2R2。

get-response数据包内容与set-request中无异。

下面Python脚本用于接收,R2发送的Trap,并做简单解析。

先运行该脚本,之后再R2上手动将一个接口shutdown,结果如下:

接口上抓包结果如下,此时团体名用的是public,data部分表明是trap。

由于Ensp中的通用路由器认证算法只支持des56,而pysnmp不支持该算法,因此使用AR路由器配置SNMPv3。

使用下面Python脚本发送snmpv3 get报文获取设备系统信息。

抓包结果如下,首先发送get-resques进行SNMPv3认证请求,随机生成一个msgID,认证模式为USM,msgflgs中Reportable置1要求对方发送report,其他为置0,表示不进行加密与鉴权;另外安全参数,认证参数、加密参数都为空,此时不携带get请求数据。

路由器给NMS回复report,msgID与resquest一致,Msgflgs中各位都置0,同时回复使用的安全引擎,认证与加密参数为空,不进行认证与加密,因此能看到data中的数据。

AR1收到请求后进行回复,数据包中msgflags标志位中除reportable外其他位都置1,表示不需要回复,同时进行加密与鉴权。同样也可以看到认证用户为testuser,认证参数与加密参数都有填充,data部分也是同样加密。

参考:

什么是SNMP - 华为 (huaweicom)

AR100-S V300R003 MIB参考 - 华为 (huaweicom)

SNMP library for Python — SNMP library for Python 44 documentation (pysnmpreadthedocsio)

python是一门无所不能的编程语言,在诸多领域都有非常不错的表现,可应用的方向也有很多,比如:

1、python爬虫工程师

python爬虫是我们比较熟悉的一个就业方向。python爬虫使用所有网络数据作为资源,通过自动化程序收集和处理目标数据。python爬虫可以做很多事情,比如搜索引擎、数据收集、广告过滤等。

python爬虫也可以用于数据分析,可以在数据抓取方面发挥巨大作用。从事python爬虫工程师的小伙伴需要精通python语言,熟悉scrapy等常用爬虫框架;熟练使用selenium、lxml、bs4对xml和html文本进行爬取、解析和清理;具有管理网站cookie有效性的经验。

2、人工智能

目前,我国人工智能的基础语言就是python。很多公司都在招聘大量与人工智能、量化交易、机器学习相关的人才。他们需要更高的学习和数学技能,以及更高的年薪。对于python新手和感兴趣的人来说,python

AI非常适合作为未来的方向。

3、数据处理

在高速互联网时代,数据可以解释很多事情。现在许多数据分析已经不像以前那么简单,python语言已经成为数据分析师的首选。许多集成到python编程语言中的图形库直接说出数据。以数据分布图的形式展示,不仅在数据统计和处理方面,很多高校实验室提取的大量实验数据也需要进行整理汇总。

而python可以发挥非常重要的作用,为工作带来极大的效率。想要在数据分析领域发展的小伙伴需要熟悉主流的数据挖掘建模算法,如数据分析、分类预测、用户画像等;掌握数据分析模型的固化和部署,能够进行数据分析和数据构建。建模、挖掘、清洗,包括数据交互、特征提取、数据挖掘、分析报告等。

4、web开发

python有很多免费的数据函数库,免费的网页模板系统,和web服务器交互的库,可以实现web开发,搭建web框架。该领域的小伙伴需要从数据、组件、安全等领域入手。从头开始学习,了解它的工作原理,并掌握业内任何主要的web框架。

5、linux运维

linux运维必须掌握python语言。python是一种非常NB的编程语言。可以满足linux运维工程师的工作需求,提高效率,普遍提升自身能力。python是一门综合性语言,可以满足绝大多数自动化运维需求,无论是前端还是后端。

想要学习Python技术,可以来老男孩试听哦~

1、Python 介绍

学习一门新的语言之前,首先简单了解下这门语言的背景。Python 是一种面向对象的解释型计算机程序设计语言,由荷兰人 Guido van Rossum 于 1989 年发明,第一个公开发行版发行于 1991 年。Python 在设计上坚持了清晰划一的风格,这使得 Python 成为一门易读、易维护,并且被大量用户所欢迎的、用途广泛的语言。Python 具有丰富和强大的库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是 C/C++)很轻松地联结在一起。

2、Python 技术浪潮

IT 行业热门技术,更新换代非常的快,技术的浪潮一波接着一波,最初的浪潮无疑是桌面时代,使用 C# 搭建桌面应用开始崭露头角,MFC 还是计算机科学专业必学会的东西。接着就是以网站搭建为应用的背景,PHP,Ruby 等语言为主的。再到近几年非常火热的以移动开发为应用背景,Java(Android 开发)或者 OC(iOS 开发)语言为主。很明显如今的浪潮就是以大数据和机器学习为应用背景,Python 语言为主。站在风尖浪口,猪都可以飞的起来。抓住这波技术浪潮,对于从事 IT 行业的人员来说有莫大的帮助。

3、Python 学习

学习一项新的技术,起步时最重要的是什么就是快速入门。学习任何一个学科的知识时,都有一个非常重要的概念:最少必要知识。当需要获得某项技能的时候,一定要想办法在最短的时间里弄清楚都有哪些最少必要知识,然后迅速掌握它们。

对于快速入门 python 来说最少必要知识,有以下几点。

(1) Python 基础语法

找一本浅显易懂,例子比较好的教程,从头到尾看下去。不要看很多本,专注于一本。把里面的例程都手打一遍,搞懂为什么。推荐去看《简明python教程》,非常好的一本 Python 入门书籍。

(2)Python 实际项目

等你对 Python 的语法有了初步的认识,就可以去找些 Python 实际项目来练习。对于任何计算机编程语言来说,以实际项目为出发点,来学习新的技术,是非常高效的学习方式。在练习的过程中你会遇到各种各样的问题:基础的语法问题(关键字不懂的拼写),代码毫无逻辑,自己的思路无法用代码表达出来等等。这时候针对出现的问题,找到对应解决办法,比如,你可以重新查看书本上的知识(关于基础语法问题),可以通过谷歌搜索碰到的编译错误(编辑器提示的错误),学习模仿别人已有的代码(写不出代码)等等。已实际项目来驱动学习,会让你成长非常的快。Python 实际项目网上非常的多,大家可以自己去搜索下。合理利用网络资源,不要意味的只做伸手党。

(3) Python 的学习规划

当你把上面两点做好以后,你就已经入门了 Python,接下来就是规划好自己的以后的学习规划。能找到一个已经会 Python 的人。问他一点学习规划的建议,然后在遇到卡壳的地方找他指点。这样会事半功倍。但是,要学会搜索,学会如何更好地提问,没人会愿意回答显而易见的问题。当然如果你身边没有人会 Python,也可以在网上搜索相应的资料。

Python 可以做的事非常的多,比如:Python 可以做日常任务,比如自动备份你的MP3;可以做网站,很多著名的网站像知乎、YouTube 就是 Python 写的;可以做网络游戏的后台,很多在线游戏的后台都是 Python 开发的。每个人都有自己感兴趣的方向,有的对网站开发比较感兴趣,有的对数据处理感兴趣,有的对后台感兴趣。所以你们可以根据自己感兴趣的方向,网上搜索相关资料,加以深入的学习,规划好自己未来的方向。只要坚持,你就能精通 Python,成为未来抢手的人才。

后端编程Python3-数据库编程

对大多数软件开发者而言,术语数据库通常是指RDBMS(关系数据库管理系统), 这些系统使用表格(类似于电子表格的网格),其中行表示...
点击下载
热门文章
    确认删除?
    回到顶部