【问题标题】:python error in reading number from csv从csv读取数字时出现python错误
【发布时间】:2015-06-30 08:41:18
【问题描述】:

我有一个 csv 文件,例如 - order_id,name,address
当我尝试通过 python 将数据从 csv 插入到 postgresql 表时,它没有正确读取数字。

例如让数据成为

order_id  |  name  |  address
----------+--------+----------
5432548543| Manish | Dummy Address

它像 5.43E+9 一样读取 order_id 而不是整数。我的代码是这样的:

filename.encode('utf-8')
with open(filename) as file:
    data = csv.DictReader(file)
    cur.executemany("""Insert into temp_unicom values(%(Order Id)s,%(Name)s,%(Address)s)""", data)

这里的订单 ID、名称、地址是我的 csv 文件的标题。

如何正确格式化数据? 编辑::
链接到csv文件CSV File

【问题讨论】:

  • 也许数字被正确读取,而您只是以科学形式显示它? order_id 列是什么类型的?
  • 是varchar类型。因为很多订单id也包含字母。
  • 数字在 csv 文件中看起来正确吗?
  • 如果您使用一个包含单个条目的数据文件(比如您给出的示例) - 这有问题吗?您的 csv 看起来像我在答案中发布的那个吗?只是想弄清楚这是数据方面的问题,还是 postgres 方面的问题。
  • 大多数看起来,但有些不。当我扩展列宽时,它们会正确显示。

标签: python postgresql csv psycopg2


【解决方案1】:

当我将您提供的示例更改为 csv 时:

order_id,name,address
5432548543,Manish,Dummy Address

只需遍历行,将它们打印出来:

with open('./data.txt') as f:
    data = csv.DictReader(f)
    for row in data:
            print(l)

我明白了:

{'order_id': '5432548543', 'name': 'Manish', 'address': 'Dummy Address'}

这表明问题不在 csv 解析步骤中 - 但您应该在数据集上尝试相同的操作以仔细检查。

那么问题是 - 您的 postgres 驱动程序在做什么可能会导致问题?你用的是psycopg2吗?它会在某处进行自动投射吗?

编辑所以问题是 src 数据。有时你有科学计数法的整数。您需要在将数据传递给executemany 之前对其进行清理:

data = csv.DictReader(f)

clean_data = []
for d in data:
    clean_data.append(d)
    try:
        d['Order Id'] = str(int(float(d['Order Id'])))
    except ValueError:
        pass

cur.executemany("""Insert into temp_unicom values (%(Order Id)s, %(Name)s, %(Address)s)""", clean_data)

【讨论】:

  • python 2.x 中可能存在问题?
  • 是的,我正在使用 psycopg2
  • 我有一些 order_ids,其中包含带数字的字母。这段代码也会影响他们吗?我的意思是如果这段代码会抛出任何带有字母数字订单 ID 的错误?
  • 不,这就是我们使用try...except 块的原因。只有整数会受到影响。实际上,让我们也将它们转回字符串 - 以确保一切都是一致的。将更新答案。
  • 所以一个整数会再次从 '87176421' 到 87176421.0 到 87176421 到 '87176421'。科学记数法将是 '5.43E+3' 到 5430.0 到 5430 到 '5430'。字符串将是 'some_string' 到预期 -> 通过 -> 没有任何改变(在字典中仍然是 'some_string')。
【解决方案2】:

在发送字典之前尝试将浮点数格式化为字符串。

例子-

cur.executemany("""Insert into temp_unicom values(%(Order Id)f,%(Name)s,%(Address)s)""",dict((k,v )if k != "Order Id" else (k,'%f'%(v)) for k,v in dict1.iteritems()))

另外,将字典重命名为其他名称(例如,我重命名为 dict1 ,否则它将替换内置的 dict 函数。

【讨论】:

  • 来自 pyscopg2 文档 (initd.org/psycopg/docs/…) “变量占位符必须始终为 %s,即使不同的占位符(例如用于整数的 %d 或用于浮点数的 %f)可能看起来更多合适”
  • 查看文档,看起来executemany 应该忠实地通过字典中的任何字符串。感觉就像是 src 数据可能存在不一致的情况。
  • 尝试了一种更新的方法来更改 dict 本身以保存格式化字符串,而不是浮动。
猜你喜欢
  • 1970-01-01
  • 2018-03-11
  • 2021-07-25
  • 2014-01-16
  • 2021-05-13
  • 2015-05-29
  • 2018-06-01
  • 2013-03-27
  • 1970-01-01
相关资源
最近更新 更多