将 "True" 和 "False" 转换为 Python 布尔值,但保留其他字符串不变
Convert "True" and "False" to Python Boolean, But Leave Other Strings Unmodified
我正在开发一个使用 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 时,遍历所有列并将字符串替换为相应的值。
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)
为什么不用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)
根据上面 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
这会将所有类型匹配代码放在一个最相关的地方。
我正在开发一个使用 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 时,遍历所有列并将字符串替换为相应的值。
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)
为什么不用pandas读写呢?您可以使用 as_type()
方法
更新:
假设 test.csv
是
1,True,sada
2,False,asda
3,False,afaff
4,True,agwe
使用
读取 CSVimport 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)
根据上面 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
这会将所有类型匹配代码放在一个最相关的地方。