簡體   English   中英

使用tempfile編寫csv臨時文件

[英]Writing a csv temporary file using tempfile

所以我正在為這個類寫一個測試(編輯得更清楚):

class SpreadSheet(object):
    '''awesome docstring'''
    def __init__(self, filename):
        self.filename = filename
        self.table = []
        self.headers = []

        with open(self.filename) as csvfile:
            filereader = reader(csvfile, delimiter=',')
            for row in filereader:
                self.table.append(row)

    def create_headers(self, populations):
        ...code...

    def lookup_header(self, ltr):
        ...code...

    def write_header(self, targetfile):
        ...code...

到目前為止看起來像這樣:

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來創建一個命名對象或者實際上可以使用with open...來調用的東西。 雖然我確實得到了它的工作,我的問題是當我嘗試使用csv包將我的self.table格式化為csv格式化的原始“字符串”(換句話說就像csv文件的原始輸入) 。

有關如何以不同方式測試或使當前代碼有效的任何指示? 我再次嘗試:

  1. 弄清楚如何使用csv來完成所有格式化繁重工作,從我的self.table加載一個假的csv文件,這樣我就不必制作一個巨大的字符串格式化表達式

  2. 在測試運行時,確保偽文件與我的原始類SpreadSheet使用的with open使用

  3. 可以進一步用於運行其他函數的測試,因為它們也需要使用文件實例化SpreadSheet以執行其功能。

並且作為一個側面問題,制作一個假的“內存”文件來做這樣的事情(這是我正在嘗試上面的內容)或者只是簡單地在磁盤上制作一個實際的臨時文件並加載它是“更精簡”在測試過程中使用它並使用tearDown()函數刪除它?

self.fake_namefile在你的例子就是一個實例NamedTemporaryFile 當您執行open()調用時,您需要傳遞包含文件名的字符串,而不是NamedTemporaryFile實例。 name變量中提供了臨時文件的name

with open(self.fake_namefile.name, 'w') as fake_csv:

以下是一些建議:

  • 讓您的Spreadsheet類采用類似文件的對象而不是文件名。 這使它更通用,並允許它與其他基於流的對象一起使用。 如果你有這個,就沒有必要創建一個假文件,你可以簡單地構造一個StringIO實例進行測試。
  • 如果您已開始使用NamedTemporaryFile ,我建議您直接將其用作上下文管理器,如另一個答案中所述。
  • 您不必對NamedTemporaryFile使用delete=True選項。 而是將整個測試包裝在上下文管理器中,如下所示。
def test_stuff(self):
    with tempfile.NamedTemporaryFile() as temp_csv:
        self.write_csv_test_data(temp_csv)  # Create this to write to temp_csv file object.
        temp_csv.flush()
        temp_csv.seek(0)

        spread_sheet = SpreadSheet(temp_csv.name)
        # spread_sheet = SpreadSheet(temp_csv)  Use this if Spreadsheet takes a file-like object
        ...

更新:

這是一個僅使用類文件對象的示例,不涉及磁盤文件。

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)

NamedTemporaryFile返回一個已打開的類似文件的對象,可以在with語句中使用,不需要調用open

    self.fake_namefile = tempfile.NamedTemporaryFile(delete=False)
    with self.fake_namefile as fake_csv:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM