【问题标题】:SQL query returns blank output when running inside Python script在 Python 脚本中运行时,SQL 查询返回空白输出
【发布时间】:2018-08-02 13:57:32
【问题描述】:

我有一个 python 脚本,它应该循环一个文本文件并从文本文件的每一行收集域作为参数。然后它应该使用域作为 SQL 查询中的参数。问题是当我将 domain_name 作为参数传递时,脚本生成的 JSON 输出为空白。如果我在查询中直接在我的 sql 查询中设置 domain_name 参数,那么脚本会输出完美的 JSON 格式。正如您在我的脚本顶部 def connect_to_db() 正下方看到的那样,我开始循环浏览文本文件。我不确定我的代码中哪里出现了错误,如果有任何帮助,将不胜感激!

代码

from __future__ import print_function

try:
    import psycopg2
except ImportError:
    raise ImportError('\n\033[33mpsycopg2 library missing. pip install psycopg2\033[1;m\n')
    sys.exit(1)

import re
import sys
import json
import pprint

DB_HOST = 'crt.sh'
DB_NAME = 'certwatch'
DB_USER = 'guest'


def connect_to_db():
    filepath = 'test.txt'
    with open(filepath) as fp:
        for cnt, domain_name in enumerate(fp):
            print("Line {}: {}".format(cnt, domain_name))
            print(domain_name)
            domain_name = domain_name.rstrip()

            conn = psycopg2.connect("dbname={0} user={1} host={2}".format(DB_NAME, DB_USER, DB_HOST))
            cursor = conn.cursor()
            cursor.execute(
                "SELECT c.id, x509_commonName(c.certificate), x509_issuerName(c.certificate) FROM certificate c, certificate_identity ci WHERE c.id = ci.certificate_id AND ci.name_type = 'dNSName' AND lower(ci.name_value) = lower('%s') AND x509_notAfter(c.certificate) > statement_timestamp();".format(
                    domain_name))

            unique_domains = cursor.fetchall()

        # print out the records using pretty print
        # note that the NAMES of the columns are not shown, instead just indexes.
        # for most people this isn't very useful so we'll show you how to return
        # columns as a dictionary (hash) in the next example.
            pprint.pprint(unique_domains)

            outfilepath = domain_name + ".json"
            with open(outfilepath, 'a') as outfile:
                    outfile.write(json.dumps(unique_domains, sort_keys=True, indent=4))

if __name__ == "__main__":
    connect_to_db()

【问题讨论】:

  • 你在 sql 字符串上使用了.format,但是里面没有{}...
  • 使用format() 也是一种糟糕的形式,因为它对sql 注入开放。您要么混淆了两种字符串插值方法(您不应该使用),要么将 %s 占位符错误地用于参数化查询。
  • @SuperStew 感谢您的回复!我应该把 {} 放在哪里?
  • @roganjosh 感谢您的回复!我应该使用什么来代替 format()?
  • @bedford 无论你想让domain_name 去哪里

标签: python sql json python-3.x


【解决方案1】:

不要使用格式来创建您的 SQL 语句。采用 ?占位符,然后是要插入的值的元组:

c.execute('''SELECT c.id, x509_commonName(c.certificate), 
    x509_issuerName(c.certificate) FROM certificate c, certificate_identity ci WHERE 
    c.id= ci.certificate_id AND ci.name_type = 'dNSName' AND lower(ci.name_value) = 
    lower(?) AND x509_notAfter(c.certificate) > statement_timestamp()''',(domain_name,))

更笼统地说:

c.execute('''SELECT columnX FROM tableA where columnY = ? AND columnZ =?'''
    (desired_columnY_value,desired_columnZ_value))

【讨论】:

  • @roganjosh 啊,我现在看到了dNSName,你是对的。但是为什么"""''' 很重要?它们和python一样吗?
  • 我不明白你的评论 roganjosh。 ''' 是 python 中多行字符串的标准。我总是将它用于 SQL 语句,因为它们可能会增长!另外,使用 ?并允许 cursor.execute() 插入值是记录在案的方法。见github.com/mkleehammer/pyodbc/wiki/Cursor
  • @SuperStew 是的,这是我的误读。但我认为编辑它以使用 """ 将使 SO 格式正确。我不敢在手机上试。
  • @T_Burgis 感谢您的回答!我尝试实现该代码并得到以下回溯: Traceback(最近一次调用最后一次):文件“5:33pm”,第 43 行,在 connect_to_db() 文件“5:33pm”,第 32 行,在 connect_to_db 下(?) AND x509_notAfter(c.certificate) > statement_timestamp()''',(domain_name)) psycopg2.ProgrammingError: 在“)”处或附近出现语法错误 第 4 行:lower(?) AND x509_notAfter(c.certificate) > statement_timest ...
  • @TBurgis 我错了对不起。在 SO 编辑器中突出显示很不稳定。
猜你喜欢
  • 1970-01-01
  • 2020-04-23
  • 2022-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多