pandas.DataFrame.query
获取表示 Dataframe 操作的人类可读字符串,然后使用pandas.eval
对它们进行求值(在此记录)。如this question中所述,我想写下面这样的函数,它们编译查询字符串的方式不会产生flake8错误。d是“一个非常滑的斜坡”,但我不知道为什么。
以这种方式设置查询字符串的格式有什么问题?
import pandas as pd
def query_column_equality(df, a, b):
if a in df.columns:
return df.query('{} == @q'.format(a), local_dict={'q': b})
else:
raise KeyError(a)
def query_column_isin(df, a, b):
if a in df.columns:
return df.query('{}.isin(@q)'.format(a), local_dict={'q': b})
else:
raise KeyError(a)
df = pd.DataFrame({'a': [1, 2], 'b': [10, 20]})
query_value = 20
print(query_column_equality(df, 'b', query_value))
query_iterable = [20]
print(query_column_isin(df, 'b', query_iterable))
1条答案
按热度按时间8zzbczxx1#
有人告诉我,格式化即将被求值的字符串是“一个极其危险的斜坡”,但我不知道为什么。
我认为这是一个很好的建议。我认为有些问题只能用eval()来解决,但是99%的使用eval()的代码可以用其他方法来更容易、更安全地解决。
我会把这个算在99%里。
例如,这两种方法都可以以更安全的方式重写:
可变为:
我的问题是这里的代码是否有风险--对列的检查是否足以安全地运行查询?
不,我不这么认为。想象一下,你在程序的某个地方使用read_csv加载了一个不可信的CSV。CSV可以合法地包含列
import os; os.system('rm -rf *')
。如果你检查你正在查询的列是否确实存在于 Dataframe 中,那么检查就会成功。有很多方法可以阻止这种情况,防止任何漏洞。但最终它们并不像使用不容易被注入的替代方法那么简单。