Python Shutil: копировать только часть файла

Код должен прочитать файл xls из каталога, преобразовать его в файл csv и скопировать в другой каталог.

filePath = os.path.join('.', 'attachments')
filePaths = [f for f in os.listdir(filePath) if os.path.isfile(os.path.join(filePath, f)) and f.endswith('.xls')]

for f in filePaths:
    wb = xlrd.open_workbook(os.path.join(filePath, f))
    sheet = wb.sheet_by_index(0)
    filename = f + '.csv'
    fp = open(os.path.join(filePath, filename), 'wb')
    wr = csv.writer(fp, quoting=csv.QUOTE_ALL)
    for rownum in xrange(sheet.nrows):
       wr.writerow(sheet.row_values(rownum))
    fp.close

    shutil.copy(os.path.join('.', 'attachments', filename), new_directory)

Результат: Файл xls успешно преобразован в файл csv, но в каталоге new_directory скопированный файл содержит только часть файла csv.

Например, в исходном CSV-файле 30 строк, а в скопированном файле всего 17 строк. Любая идея, почему это произойдет?


person Cacheing    schedule 07.08.2013    source источник


Ответы (1)


Вот ваша проблема:

fp.close

Вам нужно вызвать метод close, а не просто ссылаться на него как на метод. Так:

fp.close()

Тем не менее, ваша жизнь станет проще, если вы будете использовать операторы with вместо того, чтобы пытаться выяснить, где явно close все:

with open(os.path.join(filePath, filename), 'wb') as fp:
    wr = csv.writer(fp, quoting=csv.QUOTE_ALL)
    for rownum in xrange(sheet.nrows):
        wr.writerow(sheet.row_values(rownum))
person abarnert    schedule 07.08.2013
comment
эммм, какую глупую ошибку я совершил. Большое спасибо за ваш быстрый ответ! - person Cacheing; 07.08.2013
comment
Но я до сих пор не понимаю, почему я не получил ошибку, используя fp.close. В чем разница между fp.close и fp.close()? - person Cacheing; 07.08.2013
comment
fp.close просто получает ссылку на функцию. Это не ошибка — вы можете сохранить эту ссылку в переменной, чтобы вызвать ее позже, передать ее другой функции, которая в конечном итоге вызовет ее и т. д. () — это операция, которая вызывает функцию, т. е. , выполняет его. Таким образом, обычный вызов функции на самом деле состоит из двух частей: 1) получить ссылку на функцию (вы даете ее имя, так же, как и получить ссылку на любой другой объект), 2) вызвать ее. - person kindall; 07.08.2013
comment
@kindall Большое спасибо за объяснение! - person Cacheing; 07.08.2013