如何方便地存储和检索CSV文件中的布尔值

15 投票
4 回答
27746 浏览
提问于 2025-04-16 04:10

如果我用CSV模块存储一个布尔值,它会被转换成字符串 TrueFalse,这是因为使用了 str() 函数。但是,当我加载这些值时,字符串 False 会被判断为 True,因为它是一个非空字符串。

我可以通过在读取时手动检查这个字符串,使用IF语句来判断它是什么,但这样做显得有点笨拙。有没有更好的办法,还是说这就是编程世界中的一种常见现象呢?

4 个回答

0

使用int()这个函数可以把布尔值(也就是True和False)转换成它们对应的整数值,然后把这些值存起来。顺便提一下,eli-bendersky的评论也很值得关注。

3

其实总有更简单(而且通常更方便)的方法,而且大多数情况下,这些方法已经包含在Python强大的标准库里。

在这个例子中,你只需要使用 TrueFalse,然后用 astliteral_eval 方法来解析它们。

假设我们有一个叫 test.csv 的文件,里面的内容是:

nonetype,integer,boolean
None,123,False

我们还有一个 test.py 脚本来解析这个文件:

import ast
import csv

with open('test.csv', 'r') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        nonetype = ast.literal_eval(row['nonetype'])
        integer = ast.literal_eval(row['integer'])
        boolean = ast.literal_eval(row['boolean'])
        print(type(nonetype), type(integer), type(boolean))

当我们运行这个脚本时,可以看到值被正确解析了。

$ python3 test.py
<class 'NoneType'> <class 'int'> <class 'bool'>

这个方法使用起来也很安全,即使是来自不可信来源的输入,更多信息可以查看 官方文档

9

在CSV文件中存储布尔值的方法

  • 字符串:常见的选择有truefalse,或者TrueFalse,还有人用yesno
  • 整数:可以用01
  • 浮点数:可以用0.01.0

我们来比较一下这些方法的优缺点:

  • 字符串:
    • + 人类可以直接读懂
    • - CSV读取器会把它当作字符串处理,用bool转换时,两个都会被认为是“真”
  • 整数:
    • + CSV读取器可能会识别这一列是整数,bool(0)会被认为是假的。
    • + 占用的空间稍微少一点
    • - 不太明显这是布尔值
  • 浮点数:
    • + CSV读取器可能会识别这一列是浮点数,bool(0.0)会被认为是假的。
    • - 不太明显这是布尔值
    • + 可以表示空值(比如NaN)

Pandas的CSV读取器会表现出上述的行为。

将布尔字符串转换为布尔值

可以看看mpu.string.str2bool

>>> str2bool('True')
True
>>> str2bool('1')
True
>>> str2bool('0')
False

它的实现如下:

def str2bool(string_, default='raise'):
    """
    Convert a string to a bool.

    Parameters
    ----------
    string_ : str
    default : {'raise', False}
        Default behaviour if none of the "true" strings is detected.

    Returns
    -------
    boolean : bool

    Examples
    --------
    >>> str2bool('True')
    True
    >>> str2bool('1')
    True
    >>> str2bool('0')
    False
    """
    true = ['true', 't', '1', 'y', 'yes', 'enabled', 'enable', 'on']
    false = ['false', 'f', '0', 'n', 'no', 'disabled', 'disable', 'off']
    if string_.lower() in true:
        return True
    elif string_.lower() in false or (not default):
        return False
    else:
        raise ValueError('The value \'{}\' cannot be mapped to boolean.'
                         .format(string_))

撰写回答