Python 使用tempfile写入csv临时文件
因此,我正在为这个类编写一个测试(编辑以更清楚): 到目前为止看起来是这样的:Python 使用tempfile写入csv临时文件,python,class,unit-testing,csv,Python,Class,Unit Testing,Csv,因此,我正在为这个类编写一个测试(编辑以更清楚): 到目前为止看起来是这样的: class TestSpreadSheet(unittest.TestCase): @contextmanager def make_fake_csv(self, data): self.fake_namefile = tempfile.NamedTemporaryFile(delete=False) with open(self.fake_namefile, 'w')
class TestSpreadSheet(unittest.TestCase):
@contextmanager
def make_fake_csv(self, data):
self.fake_namefile = tempfile.NamedTemporaryFile(delete=False)
with open(self.fake_namefile, 'w') as fake_csv:
fake_writer = csv.writer(fake_csv)
fake_writer.writerows(data)
yield self.fake_namefile.name
os.unlink(self.fake_namefile.name)
def setUp(self):
self.headers = []
self.table = [
['Col1', 'Col2', 'Col3', 'Col4', 'Col5', 'Col6', 'Col7', 'Col8'],
['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'],
['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8'],
['val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8']]
def test___init__(self):
with self.make_fake_csv(self.table) as temp_csv:
spread_sheet = SpreadSheet(temp_csv)
self.assertEqual(
self.table, spread_sheet.table)
...tests for other functions...
我得到了这个错误:
in make_fake_csv
with open(self.fake_namefile, 'w') as fake_csv:
TypeError: coercing to Unicode: need string or buffer, instance found
我浏览了许多其他类似的主题,这些主题指向使用tempfile
创建命名对象,或者使用和open…
实际可以调用的对象。虽然我确实做到了这一点,但我的问题是当我试图使用csv
包将我的self.table
格式化为csv格式的原始“字符串”(换句话说,就像csv文件的原始输入)时
关于如何以不同方式进行测试或使当前代码正常工作,有什么建议吗?我再次尝试:
csv
完成所有格式化工作,从我的self.table
加载一个伪csv文件,这样我就不必制作一个巨大的字符串格式化表达式电子表格中使用的和open
一起工作
电子表格
,以执行其功能作为一个附带问题,制作一个伪“内存”文件来做这样的事情(这就是我在上面尝试的)是“更精简”还是只是在磁盘上制作一个实际的临时文件,并在测试期间加载,然后使用
tearDown()更简单
函数是否删除它?NamedTemporaryFile
返回一个已打开的类似文件的对象,该对象可以按原样在带有语句的中使用,无需调用open
:
self.fake_namefile = tempfile.NamedTemporaryFile(delete=False)
with self.fake_namefile as fake_csv:
self.fake\u namefile
在您的示例中是NamedTemporaryFile
的一个实例。执行open()
调用时,需要传递一个包含文件名的字符串,而不是NamedTemporaryFile
实例。临时文件的名称在name
变量中可用
with open(self.fake_namefile.name, 'w') as fake_csv:
以下是一些建议:
- 让您的电子表格类采用类似文件的对象,而不是文件名。这使得它更通用,并允许与其他基于流的对象一起使用。如果您有这个,就不需要创建假文件,您可以简单地构造一个
StringIO
实例进行测试
- 如果您打算使用名为temporaryfile的
,我建议您直接将其用作上下文管理器,如另一个答案中所述
- 您不必使用
delete=True
选项来NamedTemporaryFile
。相反,在上下文管理器中包装整个测试,如下所示
更新:
这是一个仅使用类似文件的对象的示例,不涉及磁盘文件
class SpreadSheet(object):
'''awesome docstring'''
def __init__(self, fileobj):
self.table = []
self.headers = []
filereader = reader(fileobj, delimiter=',')
for row in filereader:
self.table.append(row)
...
然后可以这样使用它,假设您正在从磁盘文件读取:
with open(path) as csv_file:
spreadsheet = Spreadsheet(csv_file)
....
在测试期间,您可以使用StringIO模块模拟磁盘上的文件。然后,测试运行时数据完全在内存中,因此速度非常快
import StringIO
class TestSpreadSheet(unittest.TestCase):
def make_fake_csv(self, data):
"""Return a populdated fake csv file object for testing."""
fake_csv = StringIO.StringIO()
fake_writer = csv.writer(fake_csv)
fake_writer.writerows(data)
fake_csv.seek(0)
return fake_csv
....
def test___init__(self):
temp_csv = self.make_fake_csv(self.table)
spread_sheet = SpreadSheet(temp_csv)
self.assertEqual(
self.table, spread_sheet.table)
打印self.fake_namefile
显示了什么?这是我快速修复所需要的。谢谢这太棒了,谢谢。要理解您的第一个建议,open(self.filename)
是从包含文件名的字符串创建类似文件的对象的过程吗?因此,为什么你可以用file-like-object做,
那么我就把它变成自己的行,比如file\u-object=open(self.filename)
,然后用file\u-object做为csvfile:
?@brianclements我已经更新了我的答案,希望这能回答你的一些问题。啊,我明白了。非常感谢你。通过将open(file)
函数完全放在类之外,可以使类在设计上更加模块化和可重用,这就是为什么不仅可以使用StringIO
测试它,还可以在其他模块中使用它的原因
再增加一点,使其更健壮,便于重用。查看编辑以了解详细信息。
with open(path) as csv_file:
spreadsheet = Spreadsheet(csv_file)
....
import StringIO
class TestSpreadSheet(unittest.TestCase):
def make_fake_csv(self, data):
"""Return a populdated fake csv file object for testing."""
fake_csv = StringIO.StringIO()
fake_writer = csv.writer(fake_csv)
fake_writer.writerows(data)
fake_csv.seek(0)
return fake_csv
....
def test___init__(self):
temp_csv = self.make_fake_csv(self.table)
spread_sheet = SpreadSheet(temp_csv)
self.assertEqual(
self.table, spread_sheet.table)