Самый простой способ читать / записывать содержимое файла в Python

83

В Ruby вы можете читать из файла, используя s = File.read(filename). Самый короткий и ясный, который я знаю в Python, это

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

Есть ли другой способ сделать это еще короче (желательно на одну строку) и более читабельным?

Примечание: изначально я сформулировал вопрос как «сделать это одной строкой кода». Как указал С.Лотт, короче не обязательно означает более читабельный. Поэтому я перефразировал свой вопрос, чтобы прояснить, что я имел в виду. Я думаю, что код Ruby лучше и читабельнее не обязательно потому, что это одна строка против двух (хотя это тоже имеет значение), но также потому, что это метод класса, а не метод экземпляра, который не ставит вопроса о том, кто закрывает файл, как убедиться, что он закрывается, даже если возникает исключение и т. д. Как указано в ответах ниже, вы можете положиться на GC, чтобы закрыть ваш файл (таким образом, делая его однострочным), но это еще больше ухудшает код правда короче. Не только потому, что он непереносимый, но и из-за того, что это неясно.

ibz
источник
7
Создайте свою собственную функцию. Затем вы можете использовать его для получения содержимого. Звонок будет одной строкой.
Феликс Клинг,
1
Просто любопытно, закрывает ли также файл оператор Ruby?
dheerosaur
8
-1: В кодовом гольфе никто не выигрывает.
S.Lott
4
Мой вопрос имеет для меня смысл. Я пытаюсь найти лучший способ записать эти две строки (4 строки до withутверждения в 2.5). Может, способ есть, а может, и нет. Я всегда могу попытаться выяснить, правда? Если вам это не нравится, проголосуйте против и двигайтесь дальше. :)
ibz
1
Преимущество File.readlines("filename")заключается в том, что он читает содержимое файла по его имени. Нигде в свидетельстве нет дескриптора файла, дескриптора или объекта. Все «эквиваленты» Python, которые я видел, включают явное открытие / закрытие (или, что еще хуже, неявное открытие, которое требует явного закрытия).
Марк Рид,

Ответы:

12

Если вы готовы использовать библиотеки, попробуйте установить разветвленный путь (с помощью easy_install или pip).

Тогда вы сможете:

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

Эта библиотека довольно новая, но это ответвление библиотеки, которая много лет витала вокруг Python и использовалась довольно часто. Так как я нашел это библиотека лет назад, я очень редко использую os.pathили open()больше.

снимок
источник
Похоже, хорошая библиотека. Я не буду устанавливать его только для этого, но буду иметь ввиду.
ibz
1
Я не понимаю, почему это был принятый ответ, потому что это полный взлом!
Николай 09
Разветвленный путь v0.2.3, установленный pip 18.6 в Windows, несовместим с Python 3.6.4. Похоже, что формат, используемый для восьмеричных констант (например, 0777вместо 0o0777), не поддерживается моей текущей версией Python.
Christoffer Soop
+1 к ответу Эяля Левина . Если бы pathlib или pathlib2 существовали, когда я первоначально ответил на это 8 лет назад, я бы упомянул их, а не разветвленный путь. Я не использовал разветвленный путь годами.
снимок
151
with open('x.py') as f: s = f.read()

*** усмехается ***

Марк Толонен
источник
1
Просто нет причин не писать это так, как изначально сделал OP. Намерение было ясным.
Марк Толонен
43

Это то же самое, что и выше, но не обрабатывает ошибки:

s = open(filename, 'r').read()
pyfunc
источник
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(...)мусора. Кто-нибудь поправит меня, если я ошибаюсь.
Detly
1
Это самый короткий способ сделать это. я не знаю, почему у него нет голосов.
Pritesh Acharya
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]
Eumiro
источник
4
аааааааааа! (превышение "а" для достижения минимального лимита символов)
Питер Гибсон,
6
Определенно соответствует духу вопроса ... извращенное использование Python, чтобы сделать его похожим на Bash, не хуже, чем сделать его похожим на Ruby или Perl.
подробно,
3

Вот так просто:

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

И делайте все, что хотите, с содержанием "s"

PYK
источник
-1
contents = open(filename)

Это дает вам генератор, поэтому вы должны где-то сохранить значения, или

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

Это делает сохранение для явного закрытия списка невозможным (по крайней мере, с моими знаниями Python).

Тони Вейялайнен
источник
1
и с contents = '' .join (строка для строки в open (filename)) у вас есть исходное содержимое файла ...
eumiro
Использование файла в качестве итератора вовсе не закрывает файл детерминировано (как withделает). Это невозможно, потому что после завершения итерации поиск файла и его повторное чтение все еще допустимы, что не сработает, если итерация закрыла файл.
Гленн Мейнард
@Glenn Но если вы используете генератор в понимании списка, как в моем примере, его даже невозможно закрыть, так как он не имеет имени.
Тони Вейялайнен
« Невозможно закрыть» - это не то же самое, что «закрывать не нужно».
Гленн Мейнард,
Может быть, но вы, я бы не знал, как получить доступ к этому дескриптору файла изнутри понимания списка. Может быть, должна быть команда «Завершить ввод-вывод всех файлов, закрыть все открытые файлы программы» в Python? Или может быть достаточно явного gc для файловых объектов? Однако дескриптор файла выходит за рамки, поскольку понимание списка является отдельной областью.
Тони Вейялайнен