1

我知道这个问题的其他解决方案,例如 usingwith open as,但首先我想了解为什么我的代码是或不是一个好的解决方案。

我正在尝试打开两个 CSV 文件,一个用于读取,一个用于写入。仅当成功打开两个文件时,脚本才应继续。我的代码似乎可以做到这一点,但我想知道几件事:

  1. 完成此任务的最 Pythonic 方式是什么,为什么?
  2. 从辅助函数中退出脚本是不好的做法吗?

原始代码:

input_file = 'in_file.csv'
output_file = 'out_file.csv'


def open_file(file, mode):

    try:
        fp = open(file, mode)
    except IOError as e:
        print "Error: cannot open {0}".format(file)
        if e.errno == errno.EACCES:
            print "\tPermission denied."
            print "\tError message: {0}".format(e)
            sys.exit()
        # Not a permission error.
        print "\tDoes file exist?"
        print "\tError message: {0}".format(e)
        sys.exit()
    else:
        return fp


def main():

    # Open files in binary read/write mode for platform independence.
    out_csv = open_file(output_file, 'wb')
    in_csv = open_file(input_file, 'rb')

    # Do stuff with the files
    #
    # with out_csv:
    #
    #   writer = csv.writer(out_csv, delimiter='\t')
    #
    #   with in_csv:
    #
    #       reader = csv.reader(in_csv, delimiter='\t')
    #       for row in reader:


if __name__ == '__main__':
    main()

编辑:使用 Python 2.7.2

编辑:草稿代码:

input_file = 'in_file.csv'
output_file = 'out_file.csv'


def main():

    try:
        with open(input_file, 'rb') as in_csv, open(output_file , 'wb') as out_csv:
            writer = csv.writer(out_csv, delimiter='\t')
            reader = csv.reader(in_csv, delimiter='\t')
            for row in reader:
                # continue processing
                # many lines of code...
    except IOError as e:
        print "Error: cannot open {0}".format(file)
        if e.errno == errno.EACCES:
            print "\tPermission denied."
            print "\tError message: {0}".format(e)
            sys.exit()
        # Not a permission error.
        print "\tDoes file exist?"
        print "\tError message: {0}".format(e)
        sys.exit()


if __name__ == '__main__':
    main()

我的草稿代码在 try 语句中感觉有点臃肿(想象一下另外 100 行代码)。有更好的方法吗?

4

3 回答 3

1

虽然@Inbar 的答案很简单,而且效果很好,但您可能想要花哨并实现自己的上下文管理器:

import csv
input_file = 'in_file.csv'
output_file = 'out_file.csv'


class csv_io:

    def __init__(self, input_name, output_name):
        # Open files in binary read/write mode for platform independence.
        self.input = open(input_name, 'rb')
        self.output = open(output_name, 'wb')

    def __enter__(self):
        return self

    def __exit__(self, *args):
        if hasattr(self, 'input'):
            self.input.close()
        if hasattr(self, 'output'):
            self.output.close()


def main():

    with csv_io(input_file, output_file) as data:
        writer = csv.writer(data.output, delimiter='\t')
        reader = csv.reader(data.input, delimiter='\t')
        for row in reader:
            do_stuff()

    # ...and here they are closed


if __name__ == '__main__':
    main()
于 2013-09-16T16:02:05.647 回答
1

你可以像这样很容易地做到这一切:

input_file = 'in_file.csv'
output_file = 'out_file.csv'

with open(input_file, 'rb') as in_csv, open(output_file , 'wb') as out_csv:
    # do your code
于 2013-09-16T15:52:43.790 回答
0

要回答你的第一点,你确实是对的,with open as是要走的路。这样做的原因是它确保在退出 with 语句时文件指针正确关闭。在您的示例中,如果在您的 main 函数中的某个地方引发了未处理的异常,您的脚本将退出而不关闭文件,这很糟糕。

对于第二个问题,我认为你应该在main函数中管理异常,以便于理解你的代码。

于 2013-09-16T15:55:48.713 回答