Python MySQL TypeError : must be str, 不是元组

标签 python mysql

我有以下连接到 MySQL 数据库的代码,并检查哪些记录被包含“1”的字段标记为“事件”。

代码然后使用下载 URL 中 vulntype 字段的内容下载一些文件。

我认为问题在于 MySQL 查询或执行下载的 for 循环。

代码是:-

import requests
import os
import MySQLdb
from hurry.filesize import size, si
import logging
import logging.handlers
from logging.config import fileConfig

logging.handlers = logging.handlers
fileConfig('data/logging_config.ini')
logger = logging.getLogger("downloader")


active_vuln_type = None


def get_active_vuln_sets():

    global active_vuln_type
    try:
        logging.info('Connecting to the database...')
        active_vuln_type = con = MySQLdb.connect(*******)
        logging.info('Database connected!')
    except FileNotFoundError as fnf:
        logging.error(fnf)
    except MySQLdb.Error as e:
        logging.error(e)
    try:
        logging.info('Getting active vulnerability sets...')
        cur = con.cursor()
        active = "1"
        cur.execute("""SELECT vulntype FROM vuln_sets WHERE active = %s""", (active))
        active_vuln_type = cur.fetchall()
    except MySQLdb.Error as e:
        logging.exception(e)


def download():
    try:
        logging.info('Downloading vulnerability set files...')
        for x in active_vuln_type:
            basepath = os.path.dirname(__file__)
            filepath = os.path.abspath(os.path.join(basepath, ".."))
            response = requests.get('https://vulners.com/api/'
                                    'v3/archive/collection/?type=' + x)
            with open(filepath + '/vuln_files/' + x + '.zip', 'wb') as f:
                f.write(response.content)
            filesize = size(os.path.getsize
                            (filepath + '/vuln_files/'
                             + x + '.zip'), system=si)
            files = x + ".zip - " + str(filesize)
            logging.info('Downloaded ' + x + '.zip Successfully')
            logging.info('File details: ' + files)
    except Exception as e:
        logging.exception(e)

回溯是:-

Traceback (most recent call last):
  File "/home/luke/projects/vuln_backend/vuln_backend/download.py", line 61, in download
    'v3/archive/collection/?type=' + x)
TypeError: must be str, not tuple

最佳答案

active_vuln_type = cur.fetchall()

此行返回数据库中的行列表。 每一行都是一个元组。当然,您只是从表中选择一列,但界面是相同的:每一行都是一个元组,每列一个值。

for x in active_vuln_type:

这里的 x 是一个类似 ("vulnerability of some kind",) 的元组;注意尾随的逗号。你需要解压它:

for db_row in active_vuln_type:
    x = db_row[0]  # The first and column in the row.

除此之外,请考虑描述性地命名 x,从一个过程返回 active_vuln_type 并将其作为参数传递给另一个过程。这将使您的代码不那么脆弱并且更易于测试。

def get_active_vuln_sets(db_host, db_user, db_password):
   # Do your stuff, using the db credentials....
   return active_vuln_type

def download(active_vuln_type):
   # Same source as now.

现在您可以下载(get_active_vuln_sets('192.168.100.1', 'joe', 'secret'))

或者您可以在不接触数据库的情况下测试/重试相同的操作:download([("CVE-xyxxy",), ("CVE-asdfghjkl",)])

您可以做的另一件事是返回一个干净的漏洞名称列表,而不是原始数据库元组:

def get_active_vuln_sets(...):
    # .....
    return [x[0] for x in cur.fetchall()]

现在返回的值将是一个单一的、可直接使用的值的列表,因此您的原始 download(...) 代码可以使用它。

关于Python MySQL TypeError : must be str, 不是元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46913841/

相关文章:

python - 如何将 merge_range 和 write_formula 与 xlsxwriter python 结合起来

c# - 如何从 MySql 工作台获取 MySql DB 连接信息?

mysql - MYSQl 触发器创建中的语法错误

python - 使用 SQLAlchemy 配置 connection_collat​​ion

python - 绘制多维特征的散点图

python - “ascii”编解码器无法对位置 5 : ordinal not in range(128) error 中的字符 u'\u2019' 进行编码

用于创建斐波那契数列生成器的 Python 脚本

php - PHP/MYSQL 中的类别?

php - 数据未插入数据库到表中

python - 用单个 for 遍历嵌套列表