python的fields,pythoN

发布时间:2022-11-20

本文目录一览:

  1. python怎么修改某个内存地址的数据
  2. python读取财经数据
  3. 后端编程Python3-数据库编程
  4. Python3上传中文文件名的问题

python怎么修改某个内存地址的数据

使用ctypes模块调用WriteProcessMemory函数,在创建程序进程后,就可以修改该程序指定内存地址。WriteProcessMemory的函数原型如下所示。

BOOL WriteProcessMemory(
HANDLE     hProcess,
LPVOID     lpBaseAddress,
LPCVOID    lpBuffer,
SIZE_T     nSize,
SIZE_T*    lpNumberOfBytesWritten
);

其参数含义如下:

  • hProcess:要写内存的进程句柄。
  • lpBaseAddress:要写的内存起始地址。
  • lpBuffer:写入值的地址。
  • nSize:写入值的大小。
  • lpNumberOfBytesWritten:实际写入的大小。 Python代码示例如下:
from ctypes import *
# 定义_PROCESS_INFORMATION结构体
class _PROCESS_INFORMATION(Structure):
    _fields_ = [('hProcess', c_void_p),
                ('hThread', c_void_p),
                ('dwProcessId', c_ulong),
                ('dwThreadId', c_ulong)]
# 定义_STARTUPINFO结构体
class _STARTUPINFO(Structure):
    _fields_ = [('cb', c_ulong),
                ('lpReserved', c_char_p),
                ('lpDesktop', c_char_p),
                ('lpTitle', c_char_p),
                ('dwX', c_ulong),
                ('dwY', c_ulong),
                ('dwXSize', c_ulong),
                ('dwYSize', c_ulong),
                ('dwXCountChars', c_ulong),
                ('dwYCountChars', c_ulong),
                ('dwFillAttribute', c_ulong),
                ('dwFlags', c_ulong),
                ('wShowWindow', c_ushort),
                ('cbReserved2', c_ushort),
                ('lpReserved2', c_char_p),
                ('hStdInput', c_ulong),
                ('hStdOutput', c_ulong),
                ('hStdError', c_ulong)]
NORMAL_PRIORITY_CLASS = 0x00000020  # 定义NORMAL_PRIORITY_CLASS
kernel32 = windll.LoadLibrary("kernel32.dll")  # 加载kernel32.dll
CreateProcess = kernel32.CreateProcessA  # 获得CreateProcess函数地址
ReadProcessMemory = kernel32.ReadProcessMemory  # 获得ReadProcessMemory函数地址
WriteProcessMemory = kernel32.WriteProcessMemory  # 获得WriteProcessMemory函数地址
TerminateProcess = kernel32.TerminateProcess
# 声明结构体
ProcessInfo = _PROCESS_INFORMATION()
StartupInfo = _STARTUPINFO()
file = 'ModifyMe.exe'  # 要进行修改的文件
address = 0x0040103c  # 要修改的内存地址
buffer = c_char_p("_")  # 缓冲区地址
bytesRead = c_ulong(0)  # 读入的字节数
bufferSize = len(buffer.value)  # 缓冲区大小
# 创建进程
if CreateProcess(file, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, byref(StartupInfo), byref(ProcessInfo)):
    # 读取要修改的内存地址,以判断是否是要修改的文件
    if ReadProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):
        if buffer.value == '\x74':
            buffer.value = '\x75'  # 修改缓冲区内的值,将其写入内存
            # 修改内存
            if WriteProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):
                print('成功改写内存!')
            else:
                print('写内存错误!')
        else:
            print('打开了错误的文件!')
            TerminateProcess(ProcessInfo.hProcess, 0)  # 如果不是要修改的文件,则终止进程
    else:
        print('读内存错误!')
else:
    print('不能创建进程!')

python读取财经数据

提取日期数据基本语法

from WindPy import w
w.start()

当出现.ErrorCode==-103说明没连接上,要start一下。

w.wsd(security, fields, startDate = None, endDate= None , options = None)

options可选(period, 日期类型, 货币类型,前后复权)

提取财务数据基本语法

w.wss(security, fields, options = None)

提取板块日序列基本语法

w.wses(sectorCode, fields, startDate = None, endDate = None, options = None)

提取板块日截面数据基本语法

w.wsee(sectorCode, fields, options=None)

提取宏观数据基本语法

w.edb(codes, startDate =None, endDate =None, options=None)
  1. 日期序列基本语法
ts.get_hist_data(stock, start, end)

注意:

  1. stock不能是集合,只能单个股票。
  2. 需要带上.sz.sh
  3. 没有field,只能取出数据后再切除。
  4. pro用法
pro.daily(code, start, end, fields)

tushare引用语句。 弊端也很明显,一方面不能stock集合输入,一次只能调取一个股票对应数据,另一方面tushare虽是免费试用,但有权限限制。

基本语法

wb.get_data_yahoo(code, start, end)
wb.DataReader(code, 'yahoo', start, end)

没法添加fields,虽能集合适用,但出来的索引挺奇怪的。 推荐使用定义函数或用for循环批量获取数据。 总体感觉wind API最舒服,但需要账号,mac也不能直接调用wind API。还是推荐tusharepro用法。 小白学习中,请指教=v=

后端编程Python3-数据库编程

对大多数软件开发者而言,术语数据库通常是指RDBMS(关系数据库管理系统),这些系统使用表格(类似于电子表格的网格),其中行表示记录,列表示记录的字段。表格及其中存放的数据是使用SQL(结构化查询语言)编写的语句来创建并操纵的。Python提供了用于操纵SQL数据库的API(应用程序接口),通常与作为标准的SQLite 3数据库一起发布。 另一种数据库是DBM(数据库管理器),其中存放任意数量的键-值项。Python的标准库提供了几种DBM的接口,包括某些特定于UNIX平台的。DBM的工作方式与Python中的字典类似,区别在于DBM通常存放于磁盘上而不是内存中,并且其键与值总是bytes对象,并可能受到长度限制。本章第一节中讲解的shelve模块提供了方便的DBM接口,允许我们使用字符串作为键,使用任意(picklable)对象作为值。 如果可用的 DBM 与 SQLite 数据库不够充分,Python Package Index, pypi.python.org/pypi中提供了大量数据库相关的包,包括bsddb DBM ("Berkeley DB"),对象-关系映射器,比如SQLAlchemy,以及流行的客户端/服务器数据的接口,比如 DB2、Informix、Ingres、MySQL、ODBC 以及 PostgreSQL。 本章中,我们将实现某程序的两个版本,该程序用于维护一个DVD列表,并追踪每个DVD的标题、发行年份、时间长度以及发行者。该程序的第一版使用DBM(通过shelve模块)存放其数据,第二版则使用SQLite数据库。两个程序都可以加载与保存简单的XML格式,这使得从某个程序导出DVD数据并将其导入到其他程序成为可能。与DBM版相比,基于SQL的程序提供了更多一些的功能,并且其数据设计也稍干净一些。

12.1 DBM数据库

shelve模块为DBM提供了一个wrapper,借助于此,我们在与DBM交互时,可以将其看做一个字典,这里是假定我们只使用字符串键与picklable值,实际处理时,shelve模块会将键与值转换为bytes对象(或者反过来)。 由于shelve模块使用的是底层的DBM,因此,如果其他计算机上没有同样的DBM,那么在某台计算机上保存的DBM文件在其他机器上无法读取是可能的。为解决这一问题,常见的解决方案是对那些必须在机器之间可传输的文件提供XML导入与导出功能,这也是我们在本节的DVD程序dvds-dbm.py中所做的。 对键,我们使用DVD的标题;对值,则使用元组,其中存放发行者、发行年份以及时间。借助于shelve模块,我们不需要进行任何数据转换,并可以把DBM对象当做一个字典进行处理。 程序在结构上类似于我们前面看到的那种菜单驱动型的程序,因此,这里主要展示的是与DBM程序设计相关的那部分。下面给出的是程序main()函数中的一部分,忽略了其中菜单处理的部分代码。

db = None
try:
    db = shelve.open(filename, protocol=pickle.HIGHEST_PROTOCOL)
finally:
    if db is not None:
        db.close()

这里我们已打开(如果不存在就创建)指定的DBM文件,以便于对其进行读写操作。每一项的值使用指定的pickle协议保存为一个pickle,现有的项可以被读取,即便是使用更底层的协议保存的,因为Python可以计算出用于读取pickle的正确协议。最后,DBM被关闭——其作用是清除DBM的内部缓存,并确保磁盘文件可以反映出已作的任何改变,此外,文件也需要关闭。 该程序提供了用于添加、编辑、列出、移除、导入、导出DVD数据的相应选项。除添加外,我们将忽略大部分用户接口代码,同样是因为已经在其他上下文中进行了展示。

def add_dvd(db):
    title = Console.get_string("Title", "title")
    if not title:
        return
    director = Console.get_string("Director", "director")
    if not director:
        return
    year = Console.get_integer("Year", "year", minimum=1896,
                               maximum=datetime.date.today().year)
    duration = Console.get_integer("Duration (minutes)", "minutes", minimum=0, maximum=60*48)
    db[title] = (director, year, duration)
    db.sync()

像程序菜单调用的所有函数一样,这一函数也以DBM对象(db)作为其唯一参数。该函数的大部分工作都是获取DVD的详细资料,在倒数第二行,我们将键-值项存储在DBM文件中,DVD的标题作为键,发行者、年份以及时间(由shelve模块pickled在一起)作为值。 为与Python通常的一致性同步,DBM提供了与字典一样的API,因此,除了shelve.open()函数(前面已展示)与shelve.Shelf.sync()方法(该方法用于清除shelve的内部缓存,并对磁盘上文件的数据与所做的改变进行同步——这里就是添加一个新项),我们不需要学习任何新语法。

def edit_dvd(db):
    old_title = find_dvd(db, "edit")
    if old_title is None:
        return
    title = Console.get_string("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]
    db.sync()

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

def find_dvd(db, message):
    message = "(Start of) title to " + message
    while True:
        matches = []
        start = Console.get_string(message, "title")
        if not start:
            return None
        for title in db:
            if title.lower().startswith(start.lower()):
                matches.append(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=str.lower)
            for i, match in enumerate(matches):
                print("{0}: {1}".format(i+1, match))
            which = Console.get_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,一个在程序中其他地方设置的整数),就以大小写不敏感的顺序展示所有这些匹配项,并为每一项设置一个编号,以便用户可以只输入编号就可以选择某个标题。(Console.get_integer()函数可以接受0,即便最小值大于0,以便0可以用作一个删除值。通过使用参数allow_zero=False,可以禁止这种行为。我们不能使用Enter键,也就是说,没有什么意味着取消,因为什么也不输入意味着接受默认值。)

def list_dvds(db):
    start = ""
    if len(db) > DISPLAY_LIMIT:
        start = Console.get_string("List those starting with [Enter=all]", "start")
    print()
    for title in sorted(db, key=str.lower):
        if not start or title.lower().startswith(start.lower()):
            director, year, duration = db[title]
            print("{title} ({year}) {duration} minute{0}, by "
                  "{director}".format(Util.s(duration), **locals()))

列出所有DVD(或者那些标题以某个子字符串引导)就是对DBM的所有项进行迭代。 Util.s()函数就是简单的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 = Console.get_bool("Remove {0}?".format(title), "no")
    if ans:
        del db[title]
        db.sync()

要移除一个DVD,首先需要找到用户要移除的DVD,并请求确认,获取后从DBM中删除该项即可。 到这里,我们展示了如何使用shelve模块打开(或创建)一个DBM文件,以及如何向其中添加项、编辑项、对其项进行迭代以及移除某个项。 遗憾的是,在我们的数据设计中存在一个瑕疵。发行者名称是重复的,这很容易导致不一致性,比如,发行者Danny DeVito可能被输入为"Danny De Vito",用于一个电影;也可以输入为“Danny deVito",用于另一个。为解决这一问题,可以使用两个DBM文件,主DVD文件使用标题键与(年份,时间长度,发行者ID)值;发行者文件使用发行者ID(整数)键与发行者名称值。下一节展示的SQL数据库版程序将避免这一瑕疵,这是通过使用两个表格实现的,一个用于DVD,另一个用于发行者。

12.2 SQL数据库

大多数流行的SQL数据库的接口在第三方模块中是可用的,Python带有sqlite3模块(以及SQLite 3数据库),因此,在Python中,可以直接开始数据库程序设计。SQLite是一个轻量级的SQL数据库,缺少很多诸如PostgreSQL这种数据库的功能,但非常便于构造原型系统,并且在很多情况下也是够用的。 为使后台数据库之间的切换尽可能容易,PEP 249(Python Database API Specification v2.0)提供了称为DB-API 2.0的API规范。数据库接口应该遵循这一规范,比如sqlite3模块就遵循这一规范,但不是所有第三方模块都遵循。API规范中指定了两种主要的对象,即连接对象与游标对象。表12-1与表12-2中分别列出了这两种对象必须支持的API。在sqlite3模块中,除DB-API 2.0规范必需的之外,其连接对象与游标对象都提供了很多附加的属性与方法。 DVD程序的SQL版本为dvds.sql.py,该程序将发行者与DVD数据分开存储,以避免重复,并提供一个新菜单,以供用户列出发行者。该程序使用的两个表格在图12-1中展示。

def connect(filename):
    create = not os.path.exists(filename)
    db = sqlite3.connect(filename)
    if create:
        cursor = db.cursor()
        cursor.execute("CREATE TABLE directors ("
                      "id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL, "
                      "name TEXT UNIQUE NOT NULL)")
        cursor.execute("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)")
        db.commit()
    return db

sqlite3.connect()函数会返回一个数据库对象,并打开其指定的数据库文件。如果该文件不存在,就创建一个空的数据库文件。鉴于此,在调用sqlite3.connect()之前,我们要注意数据库是否是准备从头开始创建,如果是,就必须创建该程序要使用的表格。所有查询都是通过一个数据库游标完成的,可以从数据库对象的cursor()方法获取。 注意,两个表格都是使用一个ID字段创建的,ID字段有一个AUTOINCREMENT约束——这意味着SQLite会自动为ID字段赋予唯一性的数值,因此,在插入新记录时,我们可以将这些字段留给SQLite处理。 SQLite支持有限的数据类型——实际上就是布尔型、数值型与字符串——但使用数据“适配器”可以对其进行扩展,或者是扩展到预定义的数据类型(比如那些用于日期与datetimes的类型),或者是用于表示任意数据类型的自定义类型。DVD程序并不需要这一功能,如果需要,sqlite3模块的文档提供了很多详细解释。我们使用的外部键语法可能与用于其他数据库的语法不同,并且在任何情况下,只是记录我们的意图,因为SQLite不像很多其他数据库那样需要强制关系完整性。sqlite3另一点与众不同的地方在于其默认行为是支持隐式的事务处理,因此,没有提供显式的“开始事务”方法。

def add_dvd(db):
    title = Console.get_string("Title", "title")
    if not title:
        return
    director = Console.get_string("Director", "director")
    if not director:
        return
    year = Console.get_integer("Year", "year", minimum=1896,
                               maximum=datetime.date.today().year)
    duration = Console.get_integer("Duration (minutes)", "minutes",
                                   minimum=0, maximum=60*48)
    director_id = get_and_set_director(db, director)
    cursor = db.cursor()
    cursor.execute("INSERT INTO dvds "
                  "(title, year, duration, director_id)"
                  "VALUES (?, ?, ?, ?)",
                  (title, year, duration, director_id))
    db.commit()

这一函数的开始代码与dvds-dbm.py程序中的对应函数一样,但在完成数据的收集后,与原来的函数有很大的差别。用户输入的发行者可能在也可能不在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 director_id is not None:
        return director_id
    cursor = db.cursor()
    cursor.execute("INSERT INTO directors (name) VALUES (?)", (director,))
    db.commit()
    return get_director_id(db, director)

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

def get_director_id(db, director):
    cursor = db.cursor()
    cursor.execute("SELECT id FROM directors WHERE name=?", (director,))
    fields = cursor.fetchone()
    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 = Console.get_string("Title", "title", title)
    if not title:
        return
    cursor = db.cursor()
    cursor.execute("SELECT dvds.year, dvds.duration, directors.name"
                  "FROM dvds, directors "
                  "WHERE dvds.director_id = directors.id AND "
                  "dvds.id=:id", dict(id=identity))
    year, duration, director = cursor.fetchone()
    director = Console.get_string("Director", "director", director)
    if not director:
        return
    year = Console.get_integer("Year", "year", year, 1896, datetime.date.today().year)
    duration = Console.get_integer("Duration (minutes)", "minutes",
                                   duration, minimum=0, maximum=60*48)
    director_id = get_and_set_director(db, director)
    cursor.execute("UPDATE dvds SET title=:title, year=:year, "
                  "duration=:duration, director_id=:director_id "
                  "WHERE id=:identity", locals())
    db.commit()

要编辑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 = db.cursor()
    while True:
        start = Console.get_string(message, "title")
        if not start:
            return (None, None)
        cursor.execute("SELECT title, id FROM dvds "
                      "WHERE title LIKE ? ORDER BY title",
                      (start + "%",))
        records = cursor.fetchall()
        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 = Console.get_integer("Number (or 0 to cancel)",
                                        "number", minimum=1, maximum=len(records))
            return records[which - 1] if which != 0 else (None, None)

这一函数的功能与dvdsdbm.py程序中的find_dvd()函数相同,并返回一个二元组(DVD标题,DVD ID)或(None, None),具体依赖于是否找到了某个记录。这里并不需要在所有数据上进行迭代,而是使用SQL通配符(%),因此只取回相关的记录。 由于我们希望匹配的记录数较小,因此我们一次性将其都取回到序列的序列中。如果有不止一个匹配的记录,但数量上又少到可以显示,我们就打印记录,并将每条记录附带一个数字编号,以便用户可以选择需要的记录,其方式与在dvds-dbm.py程序中所做的类似:

def list_dvds(db):
    cursor = db.cursor()
    sql = ("SELECT dvds.title, dvds.year, dvds.duration, "
           "directors.name FROM dvds, directors "
           "WHERE dvds.director_id = directors.id")
    start = None
    if dvd_count(db) > DISPLAY_LIMIT:
        start = Console.get_string("List those starting with [Enter=all]", "start")
    sql += " AND dvds.title LIKE ?"
    sql += " ORDER BY dvds.title"
    print()
    if start is None:
        cursor.execute(sql)
    else:
        cursor.execute(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 = db.cursor()
    cursor.execute("SELECT COUNT(*) FROM dvds")
    return cursor.fetchone()[0]

我们将这几行代码放置在一个单独的函数中,因为我们在几个不同的函数中都需要使用这几行代码。 我们忽略了list_directors()函数的代码,因为该函数在结构上与list_dvds()函数非常类似,只不过更简单一些,因为本函数只列出一个字段(name)。

def remove_dvd(db):
    title, identity = find_dvd(db, "remove")
    if title is None:
        return
    ans = Console.get_bool("Remove {0}?".format(title), "no")
    if ans:
        cursor = db.cursor()
        cursor.execute("DELETE FROM dvds WHERE id=?", (identity,))
        db.commit()

在用户需要删除一个记录时,将调用本函数,并且本函数与dvds-dbm.py程序中相应的函数是非常类似的。 到此,我们完全查阅了dvds-sql.py程序,并且了解了如何创建数据库表格、选取记录、在选定的记录上进行迭代以及插入、更新与删除记录。使用execute()方法,我们可以执行底层数据库所支持的任意SQL语句。 SQLite提供了比我们这里使用的多得多的功能,包括自动提交模式(以及任意其他类型的事务控制),以及创建可以在SQL查询内执行的函数的能力。提供一个工厂函数并用于控制对每个取回的记录返回什么(比如,一个字典或自定义类型,而不是字段序列)也是可能的。此外,通过传递“:memory:”作为文件名,创建内存中的SQLite数据库也是可能的。 以上内容部分摘自视频课程05后端编程Python22 数据库编程,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

Python3上传中文文件名的问题

我们之前在Python2.x的时候,用requests上传文件是正常存储中文名字,但是使用Python3之后,文件名就变得不正常了。因为Java服务端接口不支持这种方式,于是只能修改Python脚本。 因为Python3使用requests的时候,会调用urllib3库—fields.py的新处理逻辑。 当文件名是中文的时候,value = email.utils.encode_rfc2231(value, 'utf-8')就会转换格式为: filename*这种格式的键值对。 当然改源码文件是最快的,但是这样不利于移植。 还是修改下requests请求吧。