Найпростіший спосіб читати / писати вміст файлу на Python


84

У Ruby ви можете читати з файлу за допомогою s = File.read(filename). Найкоротший і зрозумілий, який я знаю в Python, - це

with open(filename) as f:
    s = f.read()

Чи є інший спосіб зробити це, що робить його ще коротшим (бажано один рядок) і більш читабельним?

Примітка: спочатку я сформулював запитання як "робити це в одному рядку коду". Як зазначив С. Лотт, коротше не обов’язково означає більше читабельність. Тож я переформулював своє запитання лише для того, щоб зрозуміти, що я мав на увазі. Я думаю, що код Ruby є кращим і зручнішим для читання, не обов'язково тому, що це один рядок проти двох (хоча це теж важливо), але також тому, що це метод класу на відміну від методу екземпляра, який не ставить під сумнів питання про те, хто закриває файл, як переконатися, що він закривається, навіть якщо виняток винятком тощо. Як зазначено у відповідях нижче, ви можете покластися на GC, щоб закрити ваш файл (тим самим роблячи це одношаровим вкладишем), але це ще більше погіршує код хоча це коротше. Не лише тим, що вони не переносяться, але й роблять це незрозумілим.


7
Створіть власну функцію. Тоді ви можете використовувати його для отримання вмісту. Дзвінок буде одним рядком.
Фелікс Клінг,

1
Просто цікаво, чи не закриває файл також і заява Ruby?
dheerosaur

8
-1: Ніхто не виграє в коде гольфі.
S.Lott,

4
Моє запитання має для мене сенс. Я намагаюся знайти кращий спосіб написати ці два рядки (4 рядки перед withтвердженням у 2.5). Можливо, є спосіб, можливо, його немає. Я завжди можу спробувати це з’ясувати, так? Якщо вам це не подобається, проголосуйте проти і рухайтеся далі. :)
ibz

1
Перевага File.readlines("filename")полягає в тому, що він читає вміст файлу із зазначенням його імені. Де-небудь в доказах немає дескриптора файлу, дескриптора або об’єкта. Усі "еквіваленти" Python, які я бачив, включають явне відкриття / закриття (або ще гірше, неявне відкриття, яке вимагає явного закриття).
Марк Рід

Відповіді:


12

Якщо ви відкриті для використання бібліотек, спробуйте встановити forked-path (за допомогою easy_install або pip).

Тоді ви можете зробити:

from path import path
s = path(filename).bytes()

Ця бібліотека є досить новою, але це розгалуження бібліотеки, яка плаває довкола Python роками і використовується досить багато. Оскільки я знайшов цю бібліотеку багато років тому, я дуже рідко користуюсь os.pathабо навіть open()більше.


Схоже на приємну бібліотеку. Я не буду встановлювати його лише для цього, але я буду це мати на увазі.
ibz

1
Я не розумію, чому це була прийнята відповідь, оскільки це суцільний хак!
nikolay

Розгалужений шлях v0.2.3, встановлений pip 18.6 у Windows, не сумісний з Python 3.6.4. Здається, формат, що використовується для вісімкових констант (наприклад, 0777замість 0o0777), не підтримується моєю поточною версією python.
Christoffer Soop

+1 до відповіді Еяла Левіна . Якби pathlib або pathlib2 існували, коли я спочатку відповідав на це 8 років тому, я б згадав їх, а не розгалужений шлях. Я роками не користувався розгалуженою стежкою.
знімок


43

Це те саме, що вище, але не обробляє помилки:

s = open(filename, 'r').read()

21
Не дуже, ваш залишає файл відкритим.
ibz,

3
Реалізація CPython закриває файл, коли кількість посилань стає нульовою, але це деталь реалізації, на яку не слід покладатися.
Марк Толонен

1
Це обробляє помилки; виняток буде створено, як зазвичай. Це не так "залишає файл відкритим", але те, що він може зробити, - це затримка наближення файлу залежно від реалізації GC. Це може бути проблемою (блокування в Windows і, наприклад, обмеження FD, якщо цикл переглядає багато файлів), але це сильно відрізняється від залишення файлу відкритим (наприклад, витік файлу).
Гленн Мейнард,

11
Якщо вашою ціллю дизайну є "один рядок коду", ви вдихнули занадто багато Perl, і вам потрібно запланувати якийсь серйозний час "немиття" мозку.
Гленн Мейнард,

6
Ні, це анітрохи не бентежить.
Гленн Мейнард

37

Використовуйте pathlib .

Python 3.5 і вище:

from pathlib import Path
contents = Path(file_path).read_text()

Для нижчих версій Python використовуйте pathlib2 :

$ pip install pathlib2

Тоді

from pathlib2 import Path
contents = Path(file_path).read_text()

Писати так само просто:

Path(file_path).write_text('my text')

18
contents = open(filename).read()

9
А коли ви закриваєте файл?
ibz

1
@ionut bizau - Коли повертається open(...)сміття, я думаю. Хтось виправте мене, якщо я помиляюся.
помер

1
Це найкоротший спосіб зробити це. я не знаю, чому він не має голосів.
Прітеш Ачарія

10

Це не Perl; ви не хочете примусово розміщувати декілька рядків на один рядок. Напишіть функцію, тоді виклик функції займає один рядок коду.

def read_file(fn):
    """
    >>> import os
    >>> fn = "/tmp/testfile.%i" % os.getpid()
    >>> open(fn, "w+").write("testing")
    >>> read_file(fn)
    'testing'
    >>> os.unlink(fn)
    >>> read_file("/nonexistant")
    Traceback (most recent call last):
        ...
    IOError: [Errno 2] No such file or directory: '/nonexistant'
    """
    with open(fn) as f:
        return f.read()

if __name__ == "__main__":
    import doctest
    doctest.testmod()

5

Повільний, потворний, специфічний для платформи ... але однокласний ;-)

import subprocess

contents = subprocess.Popen('cat %s' % filename, shell = True, stdout = subprocess.PIPE).communicate()[0]

4
ааааааааааааааа! (надлишок значень “a” відповідає мінімальним лімітам)
Пітер Гібсон,

6
Безумовно, відповідає духу питання ... збочене використання Python, щоб зробити його схожим на Bash, не гірше, ніж зробити його схожим на Ruby чи Perl.
суто

3

Просто так:

    f=open('myfile.txt')
    s=f.read()
    f.close()

І робити все, що завгодно, із вмістом "s"


-1
contents = open(filename)

Це дає вам генератор, тому ви повинні десь зберегти значення, хоча, або

contents = [line for line in open(filename)]

Це робить збереження у списку явного закриття неможливим (принаймні з моїм знанням Python).


1
а з content = '' .join (рядок для рядка відкритим (ім'я файлу)) у вас є оригінальний вміст файлу ...
eumiro

Використання файлу в якості ітератора не закриває файл детерміновано (як withце робить). Це не може, тому що після завершення ітерації все ще дійсно шукати файл і почати читати знову, що не спрацювало б, якщо ітерація закрила файл.
Гленн Мейнард,

@Glenn Але якщо ви використовуєте генератор для розуміння списку, як мій приклад, навіть закрити його неможливо, оскільки він не має назви.
Тоні Вейялайнен

" Неможливість закрити" - це не те саме, що "не потрібно закривати".
Гленн Мейнард,

Можливо, так, але ви, я б не знав, як отримати доступ до цього дескриптора файлу з розуміння списку. Чи має бути команда "закінчив усі файли вводу / виводу, закрити всі програми, відкриті файли" в Python? А може бути достатньо явного gc для файлових об'єктів? Дескриптор файлу, однак, поза сферою дії, оскільки розуміння списку є окремою сферою.
Тоні Вейялайнен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.