Открыть файл для чтения / записи, при необходимости создать

Каков самый элегантный способ открыть файл таким образом, чтобы

  • файл создается, если он не существует,
  • файл не будет усечен, если он существует и
  • можно написать любую часть файла (после поиска), а не только конец?

Насколько я могу судить, open встроенная функция не соответствует задаче: она предоставляет различные режимы, но каждый из моих попыток не удовлетворяет хотя бы одному из моих требований:

  • r+ сбой, если файл не существует.
  • w+ будет усекать файл, потеряв любой существующий контент.
  • a+ заставит все записи перейти в конец файла, по крайней мере, на мою ОС X.

Проверка на наличие до открытия файла кажется плохим, поскольку он оставляет место для условий гонки. То же самое относится к повторной попытке открытия в другом режиме из обработчика исключений. Надеюсь, что есть лучший способ.

Вам нужно использовать os.open() чтобы открыть его на более низком уровне в ОС, чем позволяет open() . В частности, передача os.RDWR | os.O_CREAT os.RDWR | os.O_CREAT как flags должны делать то, что вы хотите. Подробности см. На странице open(2) . Затем вы можете передать возвращаемый FD в os.fdopen() чтобы получить от него файл.

Если вы используете Python 3.3+, вы можете использовать режим x (эксклюзивный режим создания):

 try: f = open('/path/to/file', 'x+') except FileExistsError: f = open('/path/to/file', 'r+') 

Он вызывает FileExistsError если файл уже существует.

Возможно, я ошибаюсь, но я не думаю, что будет состояние гонки, если не существует нескольких потоков, а try и except blocks – это один и тот же поток? (Можно ли сделать несколько потоков?)

Это должно соответствовать задаче.

 >>>try: f=open('myfile.txt','r') except OSError: f=open('myfile.txt','w') finally: #whatever file I/O you need. 

У меня была аналогичная проблема при попытке сбросить элементы в файл в качестве словаря. Тем не менее, я импортировал json, http://docs.python.org/2/library/json.html, проверьте это, возможно, очень полезно. Не забудьте импортировать json. Это обеспечит основу для сброса и загрузки данных всякий раз, когда вам нужно. В этом случае я сбрасываю и загружаю информацию в пустой словарь. Метод try и except очень полезен, если вы хотите использовать пустой словарь. Я нахожу «r +» наиболее полезным, так как он будет читать и записывать файл.

 def dump_data(): j = json.dumps(file.text, indent=4) with open("database.txt", "w") as f: f.write(j) def load_data(): try: with open("file.txt", "r+") as f: return json.load(fp=f) except IOError: return {}