【问题标题】:Convert "True" and "False" to Python Boolean, But Leave Other Strings Unmodified将 "True" 和 "False" 转换为 Python 布尔值,但保持其他字符串不变
【发布时间】:2021-11-28 01:19:48
【问题描述】:

我正在使用 Flask-SQLAlchemy 开发一个应用程序,该应用程序需要以 .csv 格式导入和导出数据。我有导出功能,但我遇到了导入问题。

简而言之,我正在寻找一种将字符串“True”和“False”作为布尔值导入的通用方法,但任何其他字符串值作为其本身。原因是csv.DictWriter 将布尔值呈现为其字符串等价物,我需要将生成的文件导入回数据库中。

我试过ast.literal_eval(),但如果我给它“True”或“False”以外的任何值,它就会抛出一个ValueError。我可以测试列名,但当然,一旦我更改架构,它就会中断。我想用成语

reader = csv.DictReader(fh)
...
for row in reader:
...
    contact = Contact.query.get(row['id'])
    for key, value in row.items():
        setattr(contact, key, value)

谁能提出一种方法来实现我想要实现的目标?

【问题讨论】:

  • 如果数据类型很重要,则不应使用 CSV 格式。使用 JSON 或 Pickle。
  • 我需要导出到电子表格,然后导入修改后的电子表格。这就是我使用 .csv 的原因。
  • 这听起来像是X Y problem
  • @KlausD。你会建议我如何解决这个问题?

标签: python string csv type-conversion boolean


【解决方案1】:

读取 CSV 时,循环遍历所有列并将字符串替换为相应的值。

csv_data = []
with open("file.csv") as f:
    csv_f = csv.reader(f)
    for row in csv_f:
        for i, col in enumerate(row):
            if col == "True":
                row[i] = True
            elif col == "False":
                row[i] = False
        csv_data.append(row)

【讨论】:

  • 您应该将您的解决方案作为答案发布,而不是放在问题中。
【解决方案2】:

你为什么不用pandas来读写呢?您可以使用as_type() 方法轻松转换列

更新: 假设test.csv

1,True,sada
2,False,asda
3,False,afaff
4,True,agwe

阅读 CSV 文件

import pandas as pd

data = pd.read('text.csv', header=None)

检查数据:

print(data.head())
  0      1      2
0  1   True   sada
1  2  False   asda
2  3  False  afaff
3  4   True   agwe

检查类型:

print(data.dtypes)
0     int64
1      bool
2    object
dtype: object

将列转换为字符串或整数或布尔值:

data[1].as_type(str)
data[1].as_type(int)
data[1].as_type(bool)

【讨论】:

  • 你能给我举个例子吗?
  • @DarwinvonCorax 查看更新后的帖子
【解决方案3】:

根据上面 Barmar 的回答,我尝试了

for row in reader:
    if not row['id']:
        contact = Contact(**row)
        db.session.add(contact)
    else:
        contact = Contact.query.get(row['id'])
        for key, value in row.items():
            if value == "True":
                value = True
            if value == "False":
                value = False
            if value == '':
                value = None
            setattr(contact, key, value)

但后来我意识到我应该在我的模型中使用@validates 方法:

class Contact(db.Model):
...
    @validates('blacklisted', 'disabled', 'is_member')
    def string_to_bool(self, key, value):
        if isinstance(value, bool):
            return value
        if value == "True":
            return True
        if value == "False":
            return False
        if value is not None and re.match("^\s*$", value) is not None:
            return None
        return value

这会将所有类型匹配的代码放在一个最相关的地方。

【讨论】:

    猜你喜欢
    • 2011-04-27
    • 2011-12-28
    • 1970-01-01
    • 2017-01-08
    • 2020-03-08
    • 2018-03-10
    • 2020-06-02
    • 2016-04-05
    • 1970-01-01
    相关资源
    最近更新 更多