Python3 unicode转义

Python3 unicode转义,python,sqlite,python-3.7,unicode-escapes,Python,Sqlite,Python 3.7,Unicode Escapes,我有一个脚本,是按照《为取证学习Python》一书中的蓝图构建的。脚本将遍历用户指定的目录,并收集目录中每个文件的元数据。结果将保存到sqlite数据库,并写入CSV或HTML文件 该脚本最初是用Python 2.7.15编写的。我正在尝试更新Python 3.7的代码。但是,ingest目录函数中有一行给了我一些问题 ingestDirectory函数如下所示: def ingestDirectory(cur, source, custodian_id): count = 0

我有一个脚本,是按照《为取证学习Python》一书中的蓝图构建的。脚本将遍历用户指定的目录,并收集目录中每个文件的元数据。结果将保存到sqlite数据库,并写入CSV或HTML文件

该脚本最初是用Python 2.7.15编写的。我正在尝试更新Python 3.7的代码。但是,ingest目录函数中有一行给了我一些问题

ingestDirectory
函数如下所示:

def ingestDirectory(cur, source, custodian_id):    
    count = 0
    for root, folders, files in os.walk(source):
        for file_name in files:
            meta_data = dict()
            try:
                meta_data['file_name'] = file_name
                meta_data['file_path'] = os.path.join(root, file_name)
                meta_data['extension'] = os.path.splitext(file_name)[-1]

                file_stats = os.stat(meta_data['file_path'])
                meta_data['mode'] = oct(file_stats.st_mode)
                meta_data['inode'] = int(file_stats.st_ino)
                meta_data['file_size'] = int(file_stats.st_size)
                meta_data['atime'] = formatTimestamp(file_stats.st_atime)
                meta_data['mtime'] = formatTimestamp(file_stats.st_mtime)
                meta_data['ctime'] = formatTimestamp(file_stats.st_ctime)
            except Exception as e:
                logging.error('Could not gather data for file: ' + meta_data['file_path'] + e.__str__())
            meta_data['custodian'] = custodian_id
            columns = '","'.join(meta_data.keys())
            values = '","'.join(str(x).encode('string_escape') for x in meta_data.values())
            sql = 'INSERT INTO Files ("' + columns + '") VALUES ("' + values + '")'
            cur.execute(sql)
            count += 1
给我带来错误的一行是:

values = '","'.join(str(x).encode('string_escape') for x in meta_data.values())
此行用于在将数据写入数据库之前处理
metadata.values
中找到的任何字符串转义字符

当我试图在Python3中运行这段代码时,我遇到了一个关于无法识别的编解码器的错误。我做了一些关于堆栈溢出的研究,发现在Python3中,
string\u escape
已被
unicode escape
取代

我对Python 3和Unicode相当陌生。我的问题是:

如何更新上面的行,使其使用
unicode转义
而不是
string\u转义
,并生成与Python 2.7代码相同的结果


任何帮助都将不胜感激!我已经为此工作了好几天了,我尝试的每一个解决方案都会导致更多的错误代码或损坏的输出文件。

您正在这段代码中生成SQL,而Escape就是为了尝试生成有效的SQL。这是一个非常可怜的人试图避免SQL注入。它不是很有效,也不需要,因为数据库驱动程序已经知道如何以更安全的方式处理这个问题了

对于SQL数据库,将值放入SQL参数的正确方法。SQL参数由两个组件组成:占位符和分别传递给
.execute()
方法的值,以便数据库干净地处理。
sqlite3
库也不例外,请参阅。对于您的情况,可以使用命名占位符:

columns = [f'''"{name.replace('"', '""')}"''' for name in meta_data]
placeholders = [f':{name}' for name in meta_data]
sql = f'INSERT INTO Files ({", ".join(columns)}) VALUES ({", ".join(placeholders)})'    
cur.execute(sql, meta_data)
注意,
元数据
作为第二个参数传递;数据库获取每个
:name
占位符,并从
元数据
字典中获取该占位符的值

我还正确设置了列名的格式,在列名周围加上双引号,并将名称中的任何
字符加倍;请参阅:

您的代码对这些列名进行了硬编码,它们都不是保留的SQL关键字,因此它们实际上不需要这种保护,但这仍然是一种良好的做法

对于您的代码,
meta_data
具有固定数量的键,上面构建了这个
sql
字符串:

>>> columns = [f'''"{name.replace('"', '""')}"''' for name in meta_data]
>>> placeholders = [f':{name}' for name in meta_data]
>>> sql = f'INSERT INTO Files ({", ".join(columns)}) VALUES ({", ".join(placeholders)})'
>>> from pprint import pprint
>>> pprint(sql)
('INSERT INTO Files ("file_name", "file_path", "extension", "mode", "inode", '
 '"file_size", "atime", "mtime", "ctime") VALUES (:file_name, :file_path, '
 ':extension, :mode, :inode, :file_size, :atime, :mtime, :ctime)')
我还将更改记录错误的方式,而不是

logging.error('Could not gather data for file: ' + meta_data['file_path'] + e.__str__())
我会用

logging.exception('Could not gather data for file: %s', meta_data['file_path'])

并将错误收集留给日志框架。即使您确实包含异常对象,也可以使用
str(e)
%s
占位符。

哦,这太好了。将来自恶意源的数据直接映射到SQL字符串中。这实际上就是“SQL注入”“@melpomene:如果这是一个控制台脚本,那就好了;用户可以直接写入sqlite数据库文件。我想知道为什么首先需要解码转义码。使用
string\u-escape
/
unicode\u-escape
是解决其他地方问题的一种方法,而不是完全控制数据时使用的工具。@MartijnPieters这本书被称为法医学Python,所以我假设这个脚本是用来分析来自可疑来源的文件的。@melpomene:这并不意味着这里所示的实践是那本书推荐的,或者可能只是用作垫脚石。该脚本分析本地目录并根据操作系统提供的数据设置值。我认为注入的机会不多(只有文件名可以用于此目的)。感谢您的详细回答!我将您的代码复制到脚本中,并在columns=行中遇到两个错误。第一个是扫描字符串文字时的EOL。我注意到在括号中逗号的左边你用了“'”,右边你用了“'”。我删除了一组双引号并修复了EOL错误。当我再次运行代码时,我得到了语法错误:f字符串错误:不匹配的“[”,“(”,或“{”。控制台在[just after columns=。我不确定错误的来源是什么。所有的括号似乎都匹配。@JSchaefer2516:很抱歉,我修复了字符串定义。没关系!谢谢你修复它。我更新了行,当我再次运行代码时,我得到了另一个错误。这一个在sql行中。它是:SyntaxError:f-string:expecting'}“。我试图通过将f字符串括在三个单引号中来修复它,就像您在列行中所做的那样。但是,这导致了另一个错误。这是一个sql操作错误。它所说的只是”“文件附近的错误”"。我不知道这是什么意思,也不知道它在哪里找到了这样编写的文件。你能帮忙吗?更新:好的。因此,我通过将整个INSERT语句括在单引号中修复了f-string语法错误。我找到了几个这样做的示例,所以我能想到的最好的结果是python 3需要它。但是,我仍然得到了sqlite3.Op操作错误:“文件名”附近:语法错误消息。我能想到的唯一一件事是,由于某种原因,dict的键名被双引号引用,这导致sql中出现语法错误。但是,我不知道是什么原因导致sql以这种方式读取dict键。它们在代码中没有双引号。任何帮助都会很好!@JSchaefer2516:我将看看w帽子也在上面,对不起,我有几件不同的东西需要注意。
logging.exception('Could not gather data for file: %s', meta_data['file_path'])