首页 > 解决方案 > 将字典中的键打印为不带引号的元组

问题描述

我有这本字典,稍后我想将哪些键传递给 sql 语句:

dic = {'address': 'Emil-Dannecker-Straße 2, 78234 Engen',
       'addressLink': 'https://atlas.immobilienscout24.de/adresse/78234-engen-emil-dannecker-str-2',
      'date': '28.12.2018',
      'distance': '85 m',
      'id': '109087587',
      'livingArea': '27 m²',
      'position': {'lat': 47.85883, 'lng': 8.76808},
      'price': '320 €',
      'priceSqm': '11,85 €/m²',
      'realtor': {'contactPageUrl': None, 'label': 'von Privat'},
      'roomCount': '1',
      'status': 'Deactivated'}

我想要的输出是这样的:

(realtor,
 distance,
 date,
 addressLink,
 status,
 roomCount,
 priceSqm,
 id,
 position,
 livingArea,
 address,
 price)

到目前为止,我已经尝试过tuple(dic.keys()),这给了我:

('realtor',
 'distance',
 'date',
 'addressLink',
 'status',
 'roomCount',
 'priceSqm',
 'id',
 'position',
 'livingArea',
 'address',
 'price')

有没有一种简单的方法可以将密钥转换为所需的格式?

标签: pythondictionarytuples

解决方案


首先:不要使用用户提供的输入来生成 SQL!这是SQL 注入的秘诀,这是一个重大的安全漏洞。改用SQLAlchemy之类的库来处理动态 SQL。

如果您有特定的格式要求,请不要使用内置容器。那些只有一种表示模式,旨在帮助调试。

只需直接打印您的值:

print("({})".format(",\n ".join(dic)))

这里不需要调用dic.keys(),迭代会直接给你key。

考虑到密钥的顺序可能是任意的!Python 3.6 和更新版本保留了字典中的插入顺序,但可能是您的字典的构建方式仍然给您提供了与您希望在输出中看到的顺序不同的顺序。

演示:

>>> dic = {'address': 'Emil-Dannecker-Straße 2, 78234 Engen',
...        'addressLink': 'https://atlas.immobilienscout24.de/adresse/78234-engen-emil-dannecker-str-2',
...       'date': '28.12.2018',
...       'distance': '85 m',
...       'id': '109087587',
...       'livingArea': '27 m²',
...       'position': {'lat': 47.85883, 'lng': 8.76808},
...       'price': '320 €',
...       'priceSqm': '11,85 €/m²',
...       'realtor': {'contactPageUrl': None, 'label': 'von Privat'},
...       'roomCount': '1',
...       'status': 'Deactivated'}
>>> print("({})".format(",\n ".join(dic)))
(address,
 addressLink,
 date,
 distance,
 id,
 livingArea,
 position,
 price,
 priceSqm,
 realtor,
 roomCount,
 status)

您不能可靠地将其用于 SQL 插入语句!,不仅因为存在 SQL 注入的可能性,还因为任何同时作为保留 SQL 关键字的键名都会导致错误,空格或特殊字符也会导致错误。

例如,这将是一个非常糟糕的字典来尝试变成列:

dic = {
    "select": "reserved keyword",
    'use " quotes': "contains special characters",
    "Robert'; DROP TABLE students; --": "There goes your table!",
}

您希望在列名周围使用双引号来正确转义任何有问题的值。列名中的任何双引号都应加倍。因此,要正确格式化和转义值,请使用以下命令:

columns = "({})".format(',\n '.join([
    '"{}"'.format(key.replace('"', '""'))
    for key in dic]))

这至少可以在生成列名时保护您免受 SQL 注入:

>>> dic = {
...     "select": "reserved keyword",
...     'use " quotes': "contains special characters",
...     "Robert'; DROP TABLE students; --": "There goes your table!",
... }
>>> columns = "({})".format(',\n '.join([
...     '"{}"'.format(key.replace('"', '""'))
...     for key in dic]))
>>> print(columns)
("select",
 "use "" quotes",
 "Robert'; DROP TABLE students; --")

SQLAlchemy 将为您处理此类细节,包括验证列名是否存在。


推荐阅读