Хотите ли вы попытаться удалить файл, если он существует (и потерпите неудачу, если у вас нет прав), или сделать все возможное, чтобы у вас не было ошибки?
Donal Fellows
Я хотел сделать "первое" из того, что сказал @DonalFellows. Для этого, я думаю, оригинальный код Скотта был бы хорошим подходом?
LarsH
Сделайте вызванную функцию unlinkи поместите ее в пространство имен PHP.
lama12345
1
@LarsH Смотрите второй блок кода принятого ответа. Вызывает исключение, если исключением является ошибка «нет такого файла или каталога».
jpmc26
Ответы:
613
Более питонический путь был бы:
try:
os.remove(filename)exceptOSError:pass
Хотя это занимает еще больше строк и выглядит очень некрасиво, это позволяет избежать ненужного вызова os.path.exists()и следовать соглашению Python о чрезмерном использовании исключений.
Возможно, стоит написать функцию, которая сделает это за вас:
import os, errnodef silentremove(filename):try:
os.remove(filename)exceptOSErroras e:# this would be "except OSError, e:" before Python 2.6if e.errno != errno.ENOENT:# errno.ENOENT = no such file or directoryraise# re-raise exception if a different error occurred
Но пройдет ли это, если операция удаления не удалась (файловая система только для чтения или какая-то другая непредвиденная проблема)?
Скотт С. Уилсон
136
Кроме того, тот факт, что файл существует, когда os.path.exists()выполняется, не означает, что он существует, когда os.remove()выполняется.
добро пожаловать
8
Мой +1, но чрезмерное использование исключений не является соглашением Python :) Или это?
pepr
8
@pepr Я просто с юмором критиковал, что исключения являются частью нормального поведения в python. Например, итераторы должны вызывать исключения, чтобы прекратить итерации.
Мэтт
5
+1, потому что я не могу +2. Помимо того, что он более Pythonic, он на самом деле правильный, в то время как оригинал - нет, по той причине, которую предложил любезно. Подобные гоночные условия приводят к дырам в безопасности, ошибкам, которые
трудно воспроизвести
160
Я предпочитаю подавлять исключение, а не проверять наличие файла, чтобы избежать ошибки TOCTTOU . Ответ Мэтта является хорошим примером этого, но мы можем немного упростить его в Python 3, используя contextlib.suppress():
import contextlib
with contextlib.suppress(FileNotFoundError):
os.remove(filename)
Если filenameэто pathlib.Pathобъект, а не строка, мы можем вызвать его .unlink()метод вместо использования os.remove(). По моему опыту, объекты Path более полезны, чем строки для манипулирования файловой системой.
Поскольку все в этом ответе является эксклюзивным для Python 3, это дает еще одну причину для обновления.
Это самый питонический способ, как в декабре 2015 года. Хотя Python продолжает развиваться.
Mayank Jaiswal
2
Я не нашел метода remove () для объектов pathlib.Path в Python 3.6
BrianHVB
1
@jeffbyrnes: Я бы назвал это нарушением дзен Python: «Должен быть один - и желательно только один - очевидный способ сделать это». Если бы у вас было два метода, которые делали одно и то же, вы в конечном итоге смешали бы их при запуске исходного кода, и читателю было бы труднее им следовать. Я подозреваю, что они хотели согласования unlink(2), которое является безусловно самым старым соответствующим интерфейсом здесь.
Кевин
1
@nivk: Если вам нужен exceptпункт, то вы должны использовать try/ except. Его нельзя существенно сократить, потому что у вас должна быть строка для ввода первого блока, сам блок, строка для ввода второго блока, а затем этот блок, поэтому try/ exceptуже настолько кратко, насколько это возможно.
Кевин
1
Стоит отметить, что в отличие от блока try / Кроме того, это решение означает, что вам не нужно возиться с созданием исключения, чтобы убедиться, что показатели тестового покрытия актуальны.
Thclark
50
os.path.existsвозвращает Trueдля папок, а также файлов. Попробуйте использовать, os.path.isfileчтобы проверить, существует ли файл вместо этого.
Каждый раз, когда мы проверяем существование и затем удаляемся на основе этого теста, мы открываем себя для состояния гонки. (Что, если файл исчезнет между ними?)
Алекс Л
34
В духе ответа Энди Джонса, как насчет подлинной троичной операции:
@BrianHVB Поскольку тройники существуют для выбора между двумя значениями, основанными на условии, а не на разветвлении.
bgusach
1
Я не люблю использовать исключения для управления потоком. Они затрудняют понимание кода и, что более важно, могут маскировать некоторые другие возникающие ошибки (например, проблему с разрешением, блокирующую удаление файла), которая приведет к сбою без вывода сообщений.
Эд Кинг,
11
Это не атомарно. Файл может быть удален между вызовами, чтобы существовать и удалить. Безопаснее попытаться выполнить операцию и позволить ей потерпеть неудачу.
ConnorWGarvey
1
@ nam-g-vu Просто к вашему сведению, я откатил ваши изменения, потому что вы просто добавили синтаксис исходного опрашивающего в качестве альтернативы. Так как они искали что-то другое, я не думаю, что редактирование уместно для этого конкретного ответа.
Тим Китинг
10
Начиная с Python 3.8, используйте missing_ok=Trueи pathlib.Path.unlink( документы здесь )
from pathlib importPath
my_file =Path("./dir1/dir2/file.txt")# Python 3.8+
my_file.unlink(missing_ok=True)# Python 3.7 and earlierif my_file.exists():
my_file.unlink()
Многие из вас могут не согласиться - возможно, по таким причинам, как, например, предполагаемое использование троичных растений «некрасиво», но возникает вопрос о том, следует ли нам слушать людей, привыкших к уродливым стандартам, когда они называют что-то нестандартное «некрасивым».
это чисто - я не люблю использовать исключения для управления потоком. Они затрудняют понимание кода и, что более важно, могут маскировать некоторые другие возникающие ошибки (например, проблему с разрешением, блокирующую удаление файла), которая приведет к сбою без вывода сообщений.
Эд Кинг,
2
Это не красиво, потому что предполагается, что есть только один процесс, который изменит имя файла. Это не атомно. Безопасно и правильно пытаться выполнить операцию и изящно провалиться. Раздражает, что Python не может стандартизироваться. Если бы у нас был каталог, мы бы использовали shutil, и он бы поддерживал именно то, что мы хотим.
ConnorWGarvey
2
В Python 3.4 или более поздней версии pythonic путь будет:
import os
from contextlib import suppress
with suppress(OSError):
os.remove(filename)
Что-то вроде этого? Использует преимущества оценки короткого замыкания. Если файл не существует, все условие не может быть истинным, поэтому python не будет беспокоить оценку второй части.
Это определенно не «более Pythonic» - на самом деле, это то, о чем Гвидо специально предупреждает и называет «злоупотреблением» булевыми операторами.
abarnert
1
о, я согласен - часть вопроса, заданная для однострочного пути, и это было первое, что пришло мне в голову
Энди Джонс
4
Ну, вы также можете сделать его однострочным, просто удалив символ новой строки после двоеточия ... Или, что еще лучше, Гид неохотно добавил выражение if, чтобы не дать людям "злоупотреблять булевыми операторами", и есть отличная возможность доказать что можно злоупотреблять чем угодно: os.remove ("gogogo.php"), если os.path.exists ("gogogo.php"), иначе нет. :)
Я использовал, rmкоторый может заставить удалить несуществующие файлы --preserve-rootв качестве опции rm.
--preserve-root
donot remove `/' (default)
rm --help | grep "force"-f,--force ignore nonexistent files and arguments, never prompt
Мы также можем использовать safe-rm ( sudo apt-get install safe-rm)
Safe-rm - это инструмент безопасности, предназначенный для предотвращения случайного удаления важных файлов путем замены / bin / rm оболочкой, которая проверяет заданные аргументы на предмет настраиваемого черного списка файлов и каталогов, которые никогда не следует удалять.
Сначала я проверяю, существует ли путь к папке / файлу или нет. Это предотвратит установку переменной fileToRemove /folderToRemove to the string-r / `.
Использование оболочки для чего-то этого тривиально излишне, и этот подход также не будет работать кроссплатформенно (то есть Windows).
Набла
4
Использование оболочки вместо стандартной библиотеки (например, os.remove) всегда является одним из наименее питонных / чистых способов сделать что-либо. Например, вы должны вручную обрабатывать ошибки, возвращаемые оболочкой.
Набла
1
Я добавил свой ответ, чтобы использовать rmбезопасно и предотвратить rm -r /. @JonBrave
Alper
1
rm -f --preserve-rootне достаточно хорош ( --preserve-rootвероятно, по умолчанию в любом случае). Я привел -r /в качестве примера , что если это -r /homeили что-то еще? Вы, вероятно, хотите rm -f -- $fileToRemove, но это не главное.
JonBrave
3
Не так, как вы использовали, с именем переменной (переменной среды), без кавычек и без защиты, нет. И не по этому вопросу, нет. Неосторожное os.system('rm ...')подвергание крайне опасно, извините.
unlink
и поместите ее в пространство имен PHP.Ответы:
Более питонический путь был бы:
Хотя это занимает еще больше строк и выглядит очень некрасиво, это позволяет избежать ненужного вызова
os.path.exists()
и следовать соглашению Python о чрезмерном использовании исключений.Возможно, стоит написать функцию, которая сделает это за вас:
источник
os.path.exists()
выполняется, не означает, что он существует, когдаos.remove()
выполняется.Я предпочитаю подавлять исключение, а не проверять наличие файла, чтобы избежать ошибки TOCTTOU . Ответ Мэтта является хорошим примером этого, но мы можем немного упростить его в Python 3, используя
contextlib.suppress()
:Если
filename
этоpathlib.Path
объект, а не строка, мы можем вызвать его.unlink()
метод вместо использованияos.remove()
. По моему опыту, объекты Path более полезны, чем строки для манипулирования файловой системой.Поскольку все в этом ответе является эксклюзивным для Python 3, это дает еще одну причину для обновления.
источник
unlink(2)
, которое является безусловно самым старым соответствующим интерфейсом здесь.except
пункт, то вы должны использоватьtry
/except
. Его нельзя существенно сократить, потому что у вас должна быть строка для ввода первого блока, сам блок, строка для ввода второго блока, а затем этот блок, поэтомуtry
/except
уже настолько кратко, насколько это возможно.os.path.exists
возвращаетTrue
для папок, а также файлов. Попробуйте использовать,os.path.isfile
чтобы проверить, существует ли файл вместо этого.источник
В духе ответа Энди Джонса, как насчет подлинной троичной операции:
источник
Начиная с Python 3.8, используйте
missing_ok=True
иpathlib.Path.unlink
( документы здесь )источник
Другой способ узнать, существует ли файл (или файлы), и удалить его, используя глобус модуля.
Glob находит все файлы, которые могут выбрать шаблон с подстановочным знаком * nix, и зацикливает список.
источник
Ответ Мэтта правильный для старших Питонов, а Кевин правильный для новых.
Если вы не хотите копировать функцию
silentremove
, эта функциональность отображается в path.py как remove_p :источник
это однострочник
Многие из вас могут не согласиться - возможно, по таким причинам, как, например, предполагаемое использование троичных растений «некрасиво», но возникает вопрос о том, следует ли нам слушать людей, привыкших к уродливым стандартам, когда они называют что-то нестандартное «некрасивым».
источник
В Python 3.4 или более поздней версии pythonic путь будет:
источник
Что-то вроде этого? Использует преимущества оценки короткого замыкания. Если файл не существует, все условие не может быть истинным, поэтому python не будет беспокоить оценку второй части.
источник
Поцелуй предложение:
А потом:
источник
Это еще одно решение:
источник
Другое решение с вашим собственным сообщением в исключении.
источник
Я использовал,
rm
который может заставить удалить несуществующие файлы--preserve-root
в качестве опцииrm
.Мы также можем использовать safe-rm (
sudo apt-get install safe-rm
)Сначала я проверяю, существует ли путь к папке / файлу или нет. Это предотвратит установку переменной fileToRemove
/
folderToRemoveto the string
-r / `.источник
rm
безопасно и предотвратитьrm -r /
. @JonBraverm -f --preserve-root
не достаточно хорош (--preserve-root
вероятно, по умолчанию в любом случае). Я привел-r /
в качестве примера , что если это-r /home
или что-то еще? Вы, вероятно, хотитеrm -f -- $fileToRemove
, но это не главное.os.system('rm ...')
подвергание крайне опасно, извините.