简体   繁体   English

Python MySQL TypeError:必须是str,而不是元组

[英]Python MySQL TypeError: must be str, not tuple

I have the following code which connects to a MySQL DB and checks which records are marked as 'active' by a field that has '1' in.我有以下代码连接到 MySQL 数据库并检查哪些记录被一个包含“1”的字段标记为“活动”。

The code then downloads some files using the contents of the vulntype field in the URL for the download.然后,该代码使用用于下载的 URL 中vulntype字段的内容下载一些文件。

I think the issue lies with the MySQL query or the for loop to do the downloads.我认为问题在于 MySQL 查询或 for 循环进行下载。

The code is:-代码是:-

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)

The traceback for this is:-对此的追溯是:-

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()

This line returns a list of rows from the database. 该行返回数据库中的行列表。 Each row is a tuple. 每行是一个元组。 Of course you're only selecting one column from the table, but the interface is the same: each row is a tuple, one value per column. 当然,您仅从表中选择一列,但是界面是相同的:每一行都是一个元组,每列一个值。

for x in active_vuln_type:

Here x is a tuple like ("vulnerability of some kind",) ; 这里x是一个类似的元组("vulnerability of some kind",) note the trailing comma. 请注意结尾的逗号。 You need to unpack it: 您需要打开包装:

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

Besides that, please consider naming x descriptively, returning active_vuln_type from one procedure and passing it to the other as a parameter. 除此之外,请考虑描述性地命名x ,从一个过程返回active_vuln_type并将其作为参数传递给另一个过程。 This will make your code less brittle and easier to test. 这将使您的代码不那么脆弱,更易于测试。

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.

Now you can download(get_active_vuln_sets('192.168.100.1', 'joe', 'secret')) 现在您可以download(get_active_vuln_sets('192.168.100.1', 'joe', 'secret'))

Or you can test / retry the same thing without touching the DB: download([("CVE-xyxxy",), ("CVE-asdfghjkl",)]) . 或者,您也可以在不接触数据库的情况下测试/重试同一件事: download([("CVE-xyxxy",), ("CVE-asdfghjkl",)])

One more thing you can do is to return a clean list of vuln names, not raw DB tuples: 您可以做的另一件事是返回一个干净的vuln名称列表,而不是原始DB元组:

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

Now the value returned will be a list of single, directly usable values, so your original download(...) code would work with it. 现在返回的值将是一个可直接使用的单个值的列表,因此原始的download(...)代码将可以使用它。

What you get it's a tuple, so you will need to get the first element with x[0] 您得到的是一个元组,因此您需要使用x [0]获取第一个元素

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[0])
            with open(filepath + '/vuln_files/' + x[0] + '.zip', 'wb') as f:
                f.write(response.content)
            filesize = size(os.path.getsize
                            (filepath + '/vuln_files/'
                             + x[0] + '.zip'), system=si)
            files = x[0] + ".zip - " + str(filesize)
            logging.info('Downloaded ' + x[0] + '.zip Successfully')
            logging.info('File details: ' + files)
    except Exception as e:
        logging.exception(e)

Reasons to avoid these types of errors: like you have to use try: and except function as I know.避免这些类型错误的原因:就像我知道的那样,您必须使用 try: 和 except 函数。

Fetching the data using another source may not be the exect you want.使用其他来源获取数据可能不是您想要的结果。 Is your MySQL DB getting typeerror?您的 MySQL 数据库是否出现类型错误? Do check which records are marked as 'active' by a field that has '1' in by filtering them.通过过滤它们来检查哪些记录被带有“1”的字段标记为“活动”。

str(function(argument))

And it such likes:它喜欢:

try:
print(x)
except TypeError:
print("Variable x is not defined")
except:
print("Something else went wrong")

And that's all you can pass out your variable by replacing.这就是您可以通过替换传递变量的全部内容。

I do not think it will work perfectly that you want?我不认为它会像你想要的那样完美地工作? But according to wholeblog have to understand the whole code.但是根据wholeblog必须了解整个代码。

If the statement of if and else works then they will pass out some results.如果 if 和 else 语句有效,那么它们将传递一些结果。

Thank you.谢谢你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Tkinter类“必须不是元组” TypeError Python - Tkinter Class “must be str not tuple” TypeError Python 类型错误:参数 1 必须是 str,而不是元组 - TypeError: argument 1 must be str, not tuple TypeError:元组索引必须是整数,而不是str Python / django - TypeError: tuple indices must be integers, not str Python/django Python3 类型错误:“值”必须是 str 或字节的实例,而不是元组 - Python3 TypeError: 'value' must be an instance of str or bytes, not a tuple Python TypeError: bind(): AF_.NET 地址必须是元组,而不是 str - Python TypeError: bind(): AF_INET address must be tuple, not str TypeError:元组索引必须是整数或切片,而不是str Python情绪鸣叫 - TypeError: tuple indices must be integers or slices, not str Python sentiment tweet Python xlsxwriter TypeError:元组索引必须是整数,而不是str - Python xlsxwriter TypeError: tuple indices must be integers, not str Python“ TypeError:getsockaddrarg:AF_INET地址必须为元组,而不是str” - Python “TypeError: getsockaddrarg: AF_INET address must be tuple, not str” 类型错误:元组索引必须是整数或切片,而不是 str postgres/python - TypeError: tuple indices must be integers or slices, not str postgres/python TypeError:元组索引必须是整数,而不是 str - TypeError: tuple indices must be integers, not str
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM