【问题标题】:Unable to copy data from CSV to MySQLdb using Python无法使用 Python 将数据从 CSV 复制到 MySQLdb
【发布时间】:2017-08-27 08:27:27
【问题描述】:

我是 MySQL 和 Python 的新手,我正在尝试使用 python 将一个简单的 csv 文件中的单列浮点数据读取到本地 MySQL 表中,但它反复抛出一些错误。在敲击键盘几个小时后,我纠正了一些语法错误,现在我被困在这里了。任何帮助将不胜感激。也请原谅我在这里的问题格式,因为这是我第一次。

import csv
import MySQLdb

mydb = MySQLdb.connect(host='localhost',
    user='root',
    passwd='',
    db='test1')
cursor = mydb.cursor()

csv_data = csv.reader(file('csv1.csv'))
for row in csv_data:

    cursor.execute("INSERT INTO log1(speed) values( %s )" %row)
#close the connection to the database.
mydb.commit()
cursor.close()
print "Done"

这是显示的错误:

Traceback (most recent call last):
  File "test2.py", line 13, in <module>
    cursor.execute("INSERT INTO log1(speed) values( %s )" %row)

  File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 226, in execute

    self.errorhandler(self, exc, value)
  File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorvalue
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '['85.26'] )' at line 1")

csv 文件包含如下某些测试数据:

85.26
72.67
80.12
99.86
65.64

我的数据库似乎具有以下结构:

+-------+---------+
| speed | test_id |
+-------+---------+
| 98.86 |       1 |
| 88.86 |       2 |
| 78.86 |       3 |
+-------+---------+

其中speed是需要从csv文件中读取的字段,test_id是自增主键

编辑

根据 Visweswaran 的建议,我已将代码更改如下:

import csv
import MySQLdb

mydb = MySQLdb.connect(host='localhost',
    user='root',
    passwd='',
    db='test1')
cursor = mydb.cursor()

csv_data = csv.reader(file('csv1.csv'))
for row in csv_data:
        cursor.execute("INSERT INTO log1(speed) values( %s )" %row[0])
#close the connection to the database.
mydb.commit()
cursor.close()
print "Done"

现在这似乎已经修复了 Type: List 错误,但现在我收到以下错误:

File "test2.py", line 12, in <module>
    cursor.execute("INSERT INTO log1(speed) values( %s )" %row[0])
IndexError: list index out of range

我很确定我错过了一些基本的东西并且做了一些非常愚蠢的事情,但是先生您的支持将非常有帮助。

【问题讨论】:

  • 您收到的错误消息是不言自明的,即您的查询中有错误。
  • 感谢您的快速回复。请原谅我,但我在这里完全不知所措。你能指出错误到底是什么吗?正如我所说,我对 MySQL 完全陌生,所以我真的需要一些帮助。
  • 你能描述一下你的表结构吗,比如os speed和test_id的类型是什么
  • speed 应该是 float 类型,而不是 null。 test_id 应该是 unsigned int,不为 null,auto_increment,主键
  • 查询似乎没问题,但我认为row是一个列表。使用 print type(row) 查看是否为列表。

标签: python mysql csv


【解决方案1】:

形成你的问题,我已经复制了一张这样的表格,

如果不存在则创建表log1(speed float not null, test_id int(2) unsigned primary key auto_increment);

但是该行是一个列表而不是列表中的字符串,所以我将您的查询修改了一下,

>>> if len(row) > 0:
    cursor.execute("INSERT INTO log1(speed) values( %s )" %row[0])

csv 将元组(在数据库中 - 也称为行)作为 python 列表提供。因为你只有一列,所以我添加了 row[0],它给出了每一行第一列中的值。

最后,值被插入

+-------+---------+
| speed | test_id |
+-------+---------+
| 85.26 |       1 |
| 72.67 |       2 |
| 80.12 |       3 |

Parfait 在说什么:为什么不应该使用字符串格式来构造查询

他说代码容易受到关系数据库管理系统指纹的攻击。

在您的表格中考虑以下代码:

value = input("Enter the value: ")
cursor.execute("select * from log1 where test_id = "+value)
data = cursor.fetchall()
for i in data:
    print(i['speed'])
    print(i['test_id'])

用户应该在其中输入 test_id 的值并显示速度和 test_id。

考虑一下,我是一个远程用户(攻击者)现在我输入 1,你的程序会输出这个

Enter the value: 1
1.0
1
Done

好的,它给了我速度和 test_id 并且程序运行良好。

好的,现在我将其作为精心设计的查询作为输入提供,

Enter the value: 1 order by 1--
1.0
1
Done

看到相同的输出显示,但现在当我将此查询作为输入输入值:1 order by 3-- 显示一条错误消息,所以住在偏远地方的我知道您的数据库中有一个表,它有两列。

现在,看看这个输入,

Enter the value: -1 union select 1,unhex(hex(version()))--
1.0
b'5.X.X-X'
Done

我可以得到你的数据库版本是 5.X.X(实际输出会显示确切的版本。我有点偏执)。

这种类型的攻击称为基于联合的 SQL 注入攻击。还有各种其他的分类比如blind等等,我也不愿意在这里诱导这么多。

所以按照他的建议,我会写一个查询来传递这样的参数,

cursor.execute("select * from log1 where test_id = ",value)

现在我们将尝试获取版本

Enter the value: 1 union select 1,unhex(hex(verison()))--

结果:类型错误....

即使这也不是一个完整的解决方案。有很多漏洞你必须集中注意力。

请不要担心(正如你所说的 noobie),没有人是这个安全领域的专家。这需要经验。

【讨论】:

  • 现在这似乎已经修复了类型:列表错误,但现在我收到以下错误:文件“test2.py”,第 12 行,在 cursor.execute("INSERT INTO log1( speed) values( %s )" %row[0]) IndexError: list index out of range
  • 那么该行是空的,那么为什么会抛出异常,这一定是由于文本文件末尾附加了一个普通行。这可以使用条件语句来解决。在答案中查看我的更新代码
  • 当然你应该使用parameterized query而不是字符串插值,因为一些聪明的用户可以在你的csv文件中注入Bobby Tablescursor.execute("INSERT INTO log1(speed) VALUES (%s)", row)
  • @Parfait,我已经用 RDBMS 指纹识别机制和 SQL 注入(根据我的专业知识)更新了我的答案,看看是否可以。感谢您的友好回复。
猜你喜欢
  • 2015-07-15
  • 2020-12-05
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 2018-01-05
  • 1970-01-01
  • 2018-05-10
相关资源
最近更新 更多