2017-01-07 3 views
1

Я пытаюсь выяснить, какой лучший способ открыть файл python основан на его типе.открыть файл в зависимости от того, является ли он .gz или нет

Например, у меня есть что-то основное, но это просто не кажется мне «пифоническим», и я чувствую, что он каким-то образом может быть реорганизован и написан более чистым;

def openfile(filename): 
    if read_file_from_top: 
     if not filename.endswith('.gz'): 
      with open(filename, 'r') as infile: 
       for line in infile: 
        # do something 
     else: 
      with gzip.open(filename, 'r') as infile: 
       for line in infile: 
        # do something 
    elif read_file_from_bottom: 
     if not filename.endswith('.gz'): 
      with open(filename, 'r') as infile: 
       for line in infile: 
        # do something 
     else: 
      with gzip.open(filename, 'r') as infile: 
       for line in infile: 
        # do something 

Был бы лучший способ сделать это, возможно, используя генератор? Благодарю.

+1

В чем разница между ветвью 'read_file_from_top' и ветвью' read_file_from_bottom'? И вы должны исправить отступы (если предположить, что все это должна быть одна функция). – jszakmeister

+1

Отступ был автоматическим в редакторе stackoverflows, по какой-то причине он не подбирает функцию. Но я все исправлю. 'Read_file_from_top' и' read_file_from_bottom' читают файл сверху или снизу, в основном он проходит пучок дат в хронологическом порядке, в зависимости от ввода его можно быстрее читать сверху, а не снизу. Но это всего лишь пример дилеммы, с которой я столкнулся. – user1165419

+0

Этот вопрос может быть более уместным в разделе [Обзор кода] (http://codereview.stackexchange.com/) Stack Exchange. Пожалуйста, поправьте меня, если я ошибаюсь. – Tagc

ответ

2

Вы должны отделить открытие и чтение:

def openfile(filename, mode='r'): 
    if filename.endswith('.gz'): 
     return gzip.open(filename, mode): 
    else: 
     return open(filename, mode) 

with openfile(filename, 'r') as infile: 
    for line in infile: 
     # do something 
+0

Хороший ответ, я хотел отредактировать и удалить двоеточие после «mode» », что приведет к ошибке, но не может сделать 1-значное редактирование. – jimh

2

Я думаю, что-то вроде этого, по крайней мере немного лучше:

import gzip 


def file_line_gen(filename): 
    if filename.endswith('.gz'): 
     open_fn = gzip.open 
    else: 
     open_fn = open 

    with open_fn(filename, 'r') as f: 
     for line in f: 
      yield line 


for line in file_line_gen('data.gz'): 
    # do something here 
    print repr(line) 
+0

Я бы использовал троянец, но да, это лучше. –

+0

Уважая отличия 'read_file_from_top' и' read_file_from_bottom', это всего лишь половина ответа. – ppasler

+0

@ppasler код, который он предоставил, идентичен между двумя ветвями. Без дополнительной информации, неясно, что положить туда. – jszakmeister

0

Короткое решение, используя предопределенный список важных функций:

def processFile(filepath): 
    with [open, gzip.open][0 if not filepath.endswith('.gz') else 1](filepath, 'r') as fh: 
     if read_file_from_top: 
      # do something 
     elif read_file_from_bottom: 
      # do something