Writing to a new file if it doesn't exist, and appending to a file if it does

Question:

I have a program which writes a user’s highscore to a text file. The file is named by the user when they choose a playername.

If the file with that specific username already exists, then the program should append to the file (so that you can see more than one highscore). And if a file with that username doesn’t exist (for example, if the user is new), it should create a new file and write to it.

Here’s the relevant, so far not working, code:

try: 
    with open(player): #player is the varible storing the username input
        with open(player, 'a') as highscore:
            highscore.write("Username:", player)

except IOError:
    with open(player + ".txt", 'w') as highscore:
        highscore.write("Username:", player)

The above code creates a new file if it doesn’t exist, and writes to it. If it exists, nothing has been appended when I check the file, and I get no errors.

Asked By: Bondenn

||

Answers:

It’s not clear to me exactly where the high-score that you’re interested in is stored, but the code below should be what you need to check if the file exists and append to it if desired. I prefer this method to the “try/except”.

import os
player = 'bob'

filename = player+'.txt'

if os.path.exists(filename):
    append_write = 'a' # append if already exists
else:
    append_write = 'w' # make a new file if not

highscore = open(filename,append_write)
highscore.write("Username: " + player + 'n')
highscore.close()
Answered By: qmorgan

Have you tried mode ‘a+’?

with open(filename, 'a+') as f:
    f.write(...)

Note however that f.tell() will return 0 in Python 2.x. See https://bugs.python.org/issue22651 for details.

Answered By: Eric des Courtis

Just open it in 'a' mode:

a   Open for writing. The file is created if it does not exist. The stream is positioned at the end of the file.

with open(filename, 'a') as f:
    f.write(...)

To see whether you’re writing to a new file, check the stream position. If it’s zero, either the file was empty or it is a new file.

with open('somefile.txt', 'a') as f:
    if f.tell() == 0:
        print('a new file or the file was empty')
        f.write('The headern')
    else:
        print('file existed, appending')
    f.write('Some datan')

If you’re still using Python 2, to work around the bug, either add f.seek(0, os.SEEK_END) right after open or use io.open instead.

Answered By: user

Notice that if the file’s parent folder doesn’t exist you’ll get the same error:

IOError: [Errno 2] No such file or directory:

Below is another solution which handles this case:
(*) I used sys.stdout and print instead of f.write just to show another use case

# Make sure the file's folder exist - Create folder if doesn't exist
folder_path = 'path/to/'+folder_name+'/'
if not os.path.exists(folder_path):
     os.makedirs(folder_path)

print_to_log_file(folder_path, "Some File" ,"Some Content")

Where the internal print_to_log_file just take care of the file level:

# If you're not familiar with sys.stdout - just ignore it below (just a use case example)
def print_to_log_file(folder_path ,file_name ,content_to_write):

   #1) Save a reference to the original standard output       
    original_stdout = sys.stdout   
    
    #2) Choose the mode
    write_append_mode = 'a' #Append mode
    file_path = folder_path + file_name
    if (if not os.path.exists(file_path) ):
       write_append_mode = 'w' # Write mode
     
    #3) Perform action on file
    with open(file_path, write_append_mode) as f:
        sys.stdout = f  # Change the standard output to the file we created.
        print(file_path, content_to_write)
        sys.stdout = original_stdout  # Reset the standard output to its original value

Consider the following states:

'w'  --> Write to existing file
'w+' --> Write to file, Create it if doesn't exist
'a'  --> Append to file
'a+' --> Append to file, Create it if doesn't exist

In your case I would use a different approach and just use 'a' and 'a+'.

Answered By: RtmY

Using the pathlib module (python’s object-oriented filesystem paths)

Just for kicks, this is perhaps the latest pythonic version of the solution.

from pathlib import Path 

path = Path(f'{player}.txt')
path.touch()  # default exists_ok=True
with path.open('a') as highscore:
   highscore.write(f'Username:{player}')
Answered By: ohailolcat
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.