119

I'm trying to open a file, and if the file doesn't exist, I need to create it and open it for writing. I have this so far:

#open file for reading
fn = input("Enter file to open: ")
fh = open(fn,'r')
# if file does not exist, create it
if (!fh) 
fh = open ( fh, "w")

The error message says there's an issue on the line if(!fh). Can I use exist like in Perl?

lucidbrot
  • 5,378
  • 3
  • 39
  • 68
Miguel Hernandez
  • 1,209
  • 2
  • 9
  • 3
  • 4
    Possible duplicate of [Open in Python does not create a file if it doesn't exist](http://stackoverflow.com/questions/2967194/open-in-python-does-not-create-a-file-if-it-doesnt-exist) – Kevin J. Chase Mar 05 '16 at 01:18

9 Answers9

104

For Linux users.

If you don't need atomicity you can use os module:

import os

if not os.path.exists('/tmp/test'):
    os.mknod('/tmp/test')

macOS and Windows users.

On macOS for using os.mknod() you need root permissions. On Windows there is no os.mknod() method.

So as an alternative, you may use open() instead of os.mknod()

import os

if not os.path.exists('/tmp/test'):
    with open('/tmp/test', 'w'): pass
Neuron
  • 5,141
  • 5
  • 38
  • 59
Kron
  • 1,968
  • 1
  • 15
  • 15
  • 3
    macOS [requires sudo privileges to run mknod](https://stackoverflow.com/a/32115794/446554) so this is unlikely to be portable to Mac unless you're running your python script with `sudo`. – Cory Klein Feb 15 '18 at 22:10
  • 5
    This creates a race condition between `exists()` and `open()`. – Yasushi Shoji May 01 '20 at 05:55
  • How does it create a race condition? exists() is tested before open() is executed. – openCivilisation Sep 05 '20 at 09:55
  • Because `exists()` and `open()` is two separated calls this solution is not atomic. In theory there is a time between this two function calls when another program may also check existance of a file and create it if no file found. – Kron Sep 06 '20 at 10:42
  • 2
    It does not work on Windows, os has no attribute mknod. – Timo Dec 15 '20 at 20:33
  • with open does work, but I want to write directly after open and not pass. But this does not work: `with open(readme, 'w', encoding='utf8') as f: f.write(f'## {repoCapital}\n{description}')` – Timo Dec 15 '20 at 20:40
  • module 'os' has no attribute 'mknod' – NoName Dec 06 '22 at 21:34
70

You can achieve the desired behaviour with

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

These are some valid options for the second parameter mode in open():

"""
w  write mode
r  read mode
a  append mode

w+  create file if it doesn't exist and open it in (over)write mode
    [it overwrites the file if it already exists]
r+  open an existing file in read+write mode
a+  create file if it doesn't exist and open it in append mode
"""
Neuron
  • 5,141
  • 5
  • 38
  • 59
Gajendra D Ambi
  • 3,832
  • 26
  • 30
  • 7
    `r+` does not create any file. As also mentioned [here](https://stackoverflow.com/a/13248062/6209196) and [here(in the description)](http://www.manpagez.com/man/3/fopen/) `r+` is for opening a file in reading and writing mode. Correct it as it might confuse people :) – Stam Kaly Mar 29 '18 at 12:05
  • 1
    `w+` also clears the content of the file. [Here](https://stackoverflow.com/a/1466036/209019)'s a complete (longer) description of each mode. – Joschua Sep 30 '19 at 10:51
  • 3
    It does not work on Windows: Exception has occurred: FileNotFoundError – Eric Bellet Jun 17 '20 at 15:27
39

Well, first of all, in Python there is no ! operator, that'd be not. But open would not fail silently either - it would throw an exception. And the blocks need to be indented properly - Python uses whitespace to indicate block containment.

Thus we get:

fn = input('Enter file name: ')
try:
    file = open(fn, 'r')
except IOError:
    file = open(fn, 'w')
  • 2
    I have been trying to figure out why this is preferable to `open(fn, 'a').close()`. Is it because the implicit `seek` in append may be too expensive? – kojiro Mar 28 '18 at 13:31
35

Here's a quick two-liner that I use to quickly create a file if it doesn't exists.

if not os.path.exists(filename):
    open(filename, 'w').close()
LukeSavefrogs
  • 528
  • 6
  • 15
psyFi
  • 739
  • 7
  • 21
15

Using input() implies Python 3, recent Python 3 versions have made the IOError exception deprecated (it is now an alias for OSError). So assuming you are using Python 3.3 or later:

fn = input('Enter file name: ')
try:
    file = open(fn, 'r')
except FileNotFoundError:
    file = open(fn, 'w')
cdarke
  • 42,728
  • 8
  • 80
  • 84
8

I think this should work:

#open file for reading
fn = input("Enter file to open: ")
try:
    fh = open(fn,'r')
except:
# if file does not exist, create it
    fh = open(fn,'w')

Also, you incorrectly wrote fh = open(fh, "w") when the file you wanted open was fn

Neuron
  • 5,141
  • 5
  • 38
  • 59
  • 10
    You are assuming that the file cannot be opened because it does not exist. It could be that you don't have read permissions, or the filename is invalid in some way. Bare `except` is not a good idea. – cdarke Mar 04 '16 at 23:03
  • I understand that, (now) but this will be effective enough for his level of programming, it's not like we are teaching him the etiquette of programming or prepping him for `class` though. – That One Random Scrub Mar 04 '16 at 23:07
  • 8
    OK, the poor guy comes from Perl so he needs all the help he can get. – cdarke Mar 04 '16 at 23:12
  • This made my day. We could explain the intricacies, but, I want to sleep, maybe I will explain pathing in the morning to him, or do you want to? – That One Random Scrub Mar 04 '16 at 23:14
  • 1
    You don't need to write a dissertation on effective exception handling, just give him good examples. There are other answers which do that. – Jonathon Reinhart May 13 '20 at 20:52
7

Be warned, each time the file is opened with this method the old data in the file is destroyed regardless of 'w+' or just 'w'.

with open("file.txt", 'w+') as f:
    f.write("file is opened for business")
Neuron
  • 5,141
  • 5
  • 38
  • 59
Clint Hart
  • 81
  • 1
  • 1
1

If you know the folder location and the filename is the only unknown thing,

open(f"{path_to_the_file}/{file_name}", "w+")

if the folder location is also unknown

try using

pathlib.Path.mkdir
0

First let me mention that you probably don't want to create a file object that eventually can be opened for reading OR writing, depending on a non-reproducible condition. You need to know which methods can be used, reading or writing, which depends on what you want to do with the file object.

That said, you can do it as @That One Random Scrub proposed, using try: ... except:. Actually that is the proposed way, according to the python motto "It's easier to ask for forgiveness than permission".

But you can also easily test for existence:

import os
# open file for reading
fn = input("Enter file to open: ")
if os.path.exists(fn):
    fh = open(fn, "r")
else:
    fh = open(fn, "w")
Neuron
  • 5,141
  • 5
  • 38
  • 59
Michael S.
  • 150
  • 1
  • 9
  • 1
    The comments regarding `input()` and `raw_input()` only apply to Python 2. Python 3 has replaced `raw_input()` with `input()` and the "old" use of `input()` is gone. – cdarke Feb 01 '18 at 20:26
  • That's possible and would be/is a good improvement to make it more intuitive. – Michael S. Feb 01 '18 at 22:06