Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用tempfile写入csv临时文件_Python_Class_Unit Testing_Csv - Fatal编程技术网

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)