2013-09-16 50 views
1

我知道這個問題的其他解決方案,such as using with open as,但首先我想了解爲什麼我的代碼是或不是一個好的解決方案。打開多個文件,幫助函數

我想打開兩個CSV文件,一個用於讀取,一個用於寫入。只有在兩個文件都成功打開的情況下,腳本纔會繼續。我的代碼似乎完成了,但我想知道幾件事情:

  1. 什麼是最Python的方法來完成這個,爲什麼?
  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個額外的代碼行) 。有更好的方法嗎?

+1

這也許應該去上codereview.statckoverflow.com –

+0

@Joran比斯利:感謝,從現在開始將會牢記這一點。 –

回答

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 
+0

它認爲這只是py2.7 +(不知道OP有哪些版本) –

+0

@Inbar:爲了處理文件訪問錯誤(即文件無法打開),我應該使用try/except嗎?請參閱我的文章的「草稿代碼」部分。 –

0

要回答你的第一個點,你確實是正確的,with open as是要走的路。這是因爲它確保退出with語句時文件指針正確關閉。在你的例子中,如果你的主函數的某個地方出現了未處理的異常,你的腳本將會退出而不關閉文件,這是不好的。

對於第二個問題,我認爲你應該在主函數中管理Exception,以便於理解你的代碼。

+0

優秀的解釋。謝謝! –

1

雖然@因巴爾的答案很簡單,而且效果很好,你可能要被看中,並實現自己的上下文管理器:

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() 
+0

非常感謝。我也教過很多關於OOP的知識。 –