934

What is the best way to open a file as read/write if it exists, or if it does not, then create it and open it as read/write? From what I read, file = open('myfile.dat', 'rw') should do this, right?

It is not working for me (Python 2.6.2) and I'm wondering if it is a version problem, or not supposed to work like that or what.

The bottom line is, I just need a solution for the problem. I am curious about the other stuff, but all I need is a nice way to do the opening part.

The enclosing directory was writeable by user and group, not other (I'm on a Linux system... so permissions 775 in other words), and the exact error was:

IOError: no such file or directory.

Neuron
  • 5,141
  • 5
  • 38
  • 59
trh178
  • 11,228
  • 5
  • 28
  • 37
  • 2
    As S.Mark mentioned, this should "just work". Is the enclosing directory writeable? – Rakis Jun 03 '10 at 15:12
  • 8
    muksie's answer below worked (and baloo's too for that matter), but just for completeness, the enclosing dir was writable by user and group, not other (im on a linux system... so permissions 775 in other words), and the exact error was IOError: no such file or directory. thanks for the help guys. – trh178 Jun 03 '10 at 15:24
  • 4
    make sure all the leading **folders** of the `file` exists. – Jia Gao Feb 04 '20 at 15:01
  • 1
    for me the python `open(path/filename, mode='w+')` did not work until I created the target folder was created/existed `path_2_ziplike.mkdir(parents=True, exist_ok=True) ` – Charlie Parker Nov 04 '22 at 21:08

17 Answers17

1086

You should use open with the w+ mode:

file = open('myfile.dat', 'w+')
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
muksie
  • 12,565
  • 1
  • 19
  • 14
  • 158
    `w` truncates existing file. docs: *Modes `'r+'`, `'w+'` and `'a+'` open the file for updating (note that `'w+'` truncates the file).* – SilentGhost Jun 03 '10 at 15:16
  • 6
    this did the trick. thank you. i feel like an idiot now for not reading the spec. i dont think 'rw' is even acceptable there. i must have been thinking of something else. – trh178 Jun 03 '10 at 15:21
  • 96
    Note that a+ creates a file if it does not exist and, crucially, seeks the file to the end. So if you do a read immediately after opening this way, you'll get nothing. You need to seek back to the beginning first: f.seek(0) – Nick Zalutskiy Jan 10 '12 at 05:41
  • 12
    [For the verbose, example-less documentation](http://docs.python.org/library/functions.html#open) – AJP Aug 01 '12 at 23:58
  • 192
    This is not the solution. The **problem is the directory**. Either the script lacks the permissions to create a file in that directory, or the directory simply doesn't exist. `open('myfile.dat', 'w')` is then enough. – Daniel F Apr 28 '14 at 15:14
  • 5
    If the path is pointing at a directory, make sure that directory exists: i.e. `(file = open('dir/myfile.dat', 'w+') )`, make sure the `dir` folder, aka directory exists; Python won't create that for you – Nate Anderson Jun 11 '14 at 14:20
  • 2
    This is not the solution. @TheRedPea: the OP said that the directory indeed did exist, but had 775 permissions ('o-w'), hence they couldn't write it. – smci Aug 23 '16 at 08:18
  • 1
    Exception has occurred: FileNotFoundError... This does no work – Eric Bellet Jun 17 '20 at 15:23
  • @ishandutta2007 well, if everyone disagreed with the answer, they would downvote it. – J Muzhen Sep 10 '22 at 13:33
  • for me the python `open(path/filename, mode='w+')` did not work until I created the target folder was created/existed `path_2_ziplike.mkdir(parents=True, exist_ok=True) ` – Charlie Parker Nov 04 '22 at 21:08
  • @DanielF is right. My testing shows that `w+` is not necessary for the file to be created if not existent already. `w` works if the directory is there. – Qiang Xu Apr 16 '23 at 23:04
197

The advantage of the following approach is that the file is properly closed at the block's end, even if an exception is raised on the way. It's equivalent to try-finally, but much shorter.

with open("file.dat","a+") as f:
    f.write(...)
    ...

a+ Opens a file for both appending and reading. The file pointer is at the end of the file if the file exists. The file opens in the append mode. If the file does not exist, it creates a new file for reading and writing. -Python file modes

seek() method sets the file's current position.

f.seek(pos [, (0|1|2)])
pos .. position of the r/w pointer
[] .. optionally
() .. one of ->
  0 .. absolute position
  1 .. relative position to current
  2 .. relative position from end

Only "rwab+" characters are allowed; there must be exactly one of "rwa" - see Stack Overflow question Python file modes detail.

Community
  • 1
  • 1
Qwerty
  • 29,062
  • 22
  • 108
  • 136
  • 2
    I try this with open(filename, 'a+') as myfile: and get IOError: [Errno 2] No such file or directory: - why it doesn't create the file? – Loretta Jul 29 '15 at 11:59
  • @Loretta Have you checked the value of `filename`? – Qwerty Jul 29 '15 at 12:16
  • Yes, I did. It is a unicode string. I also tried with open('{}.txt'.format(filename), 'a+') as myfile: – Loretta Jul 29 '15 at 12:32
  • I am not using a path. and I tried open('test.txt', 'a+') it gets following exception 'TypeError: coercing to Unicode: need string or buffer, file found' in the line if os.stat(myfile).st_size == 0: – Loretta Aug 10 '15 at 08:20
  • You need to properly define encoding for this to work. http://stackoverflow.com/q/728891/3701431 – Sergiy Kolodyazhnyy Aug 08 '16 at 20:47
  • I have the same problem as Loretta. I try `with open(self.save_to_filepath, 'a+') as f:` and it gives "FileNotFoundError: [Errno 2] No such file or directory". The filepath is not in Unicode, either. – chenjesu Nov 14 '21 at 23:10
  • It turns out I was using the wrong directory path- I had been running the script from 2 different current directory locations. So I used the workaround in https://stackoverflow.com/questions/918154/relative-paths-in-python and it worked fine. – chenjesu Nov 14 '21 at 23:24
  • for me the python `open(path/filename, mode='w+')` did not work until I created the target folder was created/existed `path_2_ziplike.mkdir(parents=True, exist_ok=True) ` – Charlie Parker Nov 04 '22 at 21:08
63
'''
w  write mode
r  read mode
a  append mode

w+  create file if it doesn't exist and open it in write mode
r+  open for reading and writing. Does not create file.
a+  create file if it doesn't exist and open it in append mode
'''

Assuming that you are in working directory of the file.

Example:

file_name = 'my_file.txt'
f = open(file_name, 'w+')  # open file in write mode
f.write('python rules')
f.close()

[FYI am using Python version 3.6.2]

Gajendra D Ambi
  • 3,832
  • 26
  • 30
  • 5
    Mode "w+" has the disadvantage of truncating the file, if it already exists. In many cases, this is NOT what people may want. – Kai Petzke Feb 02 '22 at 10:41
42

Good practice is to use the following:

import os

writepath = 'some/path/to/file.txt'

mode = 'a' if os.path.exists(writepath) else 'w'
with open(writepath, mode) as f:
    f.write('Hello, world!\n')
lollercoaster
  • 15,969
  • 35
  • 115
  • 173
  • 47
    It is bad to test a file before opening it, as it can lead to race conditions (file is deleted before it is opened). Race conditions can sometimes be used to exploit vulnerabilities in a system. "a+" mode is the best way to open the file: it creates a new file, and appends to existing files. Do not forget to wrap this in a try/except. – sleblanc Sep 21 '17 at 21:45
  • computing mode write or append has no interest. If file doesn't exist, append mode creates it. – Jean-François Fabre Oct 22 '19 at 11:49
36

Since python 3.4 you should use pathlib to "touch" files.
It is a much more elegant solution than the proposed ones in this thread.

from pathlib import Path

filename = Path('myfile.txt')
filename.touch(exist_ok=True)  # will create file, if it exists will do nothing
file = open(filename)

Same thing with directories:

filename.mkdir(parents=True, exist_ok=True)
Granitosaurus
  • 20,530
  • 5
  • 57
  • 82
32

Change "rw" to "w+"

Or use 'a+' for appending (not erasing existing content)

baloo
  • 7,635
  • 4
  • 27
  • 35
28
>>> import os
>>> if os.path.exists("myfile.dat"):
...     f = file("myfile.dat", "r+")
... else:
...     f = file("myfile.dat", "w")

r+ means read/write

Khorkrak
  • 3,911
  • 2
  • 27
  • 37
  • 60
    This is Unpythonic. Rather than [checking if the file exists first](http://docs.python.org/3/glossary.html#term-lbyl), one should [assume it does first, then handle the case that it doesn't](http://docs.python.org/3/glossary.html#term-eafp). – Blacklight Shining Feb 22 '14 at 04:36
  • 41
    even worse, this code is prone to a race condition. thus, after checking if the file exists, the process could be interrupted and another process could create this file. – antibus Sep 19 '14 at 07:36
  • You would also need the "w+" flag so both files will be in a read and write modes. – The Matt Dec 19 '18 at 05:48
16

For Python 3+, I will do:

import os

os.makedirs('path/to/the/directory', exist_ok=True)

with open('path/to/the/directory/filename', 'w') as f:
    f.write(...)

So, the problem is with open cannot create a file before the target directory exists. We need to create it and then w mode is enough in this case.

Chenglong Ma
  • 345
  • 3
  • 13
  • CAREFUL about this! It will truncate the content if the file exists. – NONONONONO Jan 03 '22 at 12:25
  • 1
    Hi @NONONONONO, yes, it is what `w` mode does. If you want to keep the existing content, you can use `a` append mode. Refer to [open() doc](https://docs.python.org/3/library/functions.html#open) – Chenglong Ma Jan 04 '22 at 00:50
13

Use:

import os

f_loc = r"C:\Users\Russell\Desktop\myfile.dat"

# Create the file if it does not exist
if not os.path.exists(f_loc):
    open(f_loc, 'w').close()

# Open the file for appending and reading
with open(f_loc, 'a+') as f:
    #Do stuff

Note: Files have to be closed after you open them, and the with context manager is a nice way of letting Python take care of this for you.

hostingutilities.com
  • 8,894
  • 3
  • 41
  • 51
11

My answer:

file_path = 'myfile.dat'
try:
    fp = open(file_path)
except IOError:
    # If not exists, create the file
    fp = open(file_path, 'w+')
Chien-Wei Huang
  • 1,773
  • 1
  • 17
  • 27
8

open('myfile.dat', 'a') works for me, just fine.

in py3k your code raises ValueError:

>>> open('myfile.dat', 'rw')
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    open('myfile.dat', 'rw')
ValueError: must have exactly one of read/write/append mode

in python-2.6 it raises IOError.

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
7

I think it's r+, not rw. I'm just a starter, and that's what I've seen in the documentation.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Angel Poppy
  • 95
  • 1
  • 1
6

What do you want to do with file? Only writing to it or both read and write?

'w', 'a' will allow write and will create the file if it doesn't exist.

If you need to read from a file, the file has to be exist before open it. You can test its existence before opening it or use a try/except.

Neuron
  • 5,141
  • 5
  • 38
  • 59
user49117
  • 786
  • 3
  • 9
  • 5
    Testing for existence before opening might introduce a race condition. Probably not a big deal in this case, but something to keep in mind. – Daniel Hepper Jun 08 '10 at 14:36
  • 2
    "If you need to read from a file, the file has to be exist before you open it." Thank you for saving my sanity. – Brian Peterson Jun 24 '13 at 02:48
4

Put w+ for writing the file, truncating if it exist, r+ to read the file, creating one if it don't exist but not writing (and returning null) or a+ for creating a new file or appending to a existing one.

wallabra
  • 412
  • 8
  • 17
4

If you want to open it to read and write, I'm assuming you don't want to truncate it as you open it and you want to be able to read the file right after opening it. So this is the solution I'm using:

file = open('myfile.dat', 'a+')
file.seek(0, 0)
Danilo Souza Morães
  • 1,481
  • 13
  • 18
2

So You want to write data to a file, but only if it doesn’t already exist?.

This problem is easily solved by using the little-known x mode to open() instead of the usual w mode. For example:

 >>> with open('somefile', 'wt') as f:
 ...     f.write('Hello\n')
...
>>> with open('somefile', 'xt') as f:
...     f.write('Hello\n')
...
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
FileExistsError: [Errno 17] File exists: 'somefile'
  >>>

If the file is binary mode, use mode xb instead of xt.

Stephen Ngethe
  • 1,034
  • 13
  • 24
-2
import os, platform
os.chdir('c:\\Users\\MS\\Desktop')

try :
    file = open("Learn Python.txt","a")
    print('this file is exist')
except:
    print('this file is not exist')
file.write('\n''Hello Ashok')

fhead = open('Learn Python.txt')

for line in fhead:

    words = line.split()
print(words)
Ganesh Jat
  • 19
  • 4