如果不存在,则写入新文件,如果不存在,则追加到文件


76

我有一个程序可以将用户的highscore文件写入文本文件。用户选择时,文件将由用户命名playername

如果具有该特定用户名的文件已经存在,则该程序应追加到该文件(以便您可以看到多个highscore)。并且如果不存在具有该用户名的文件(例如,如果用户是新用户),则应创建一个新文件并写入该文件。

这是相关的代码,到目前为止是行不通的:

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)

上面的代码创建一个新文件(如果不存在)并将其写入。如果存在,则在检查文件时未附加任何内容,并且不会出错。


第一条with open(player):陈述的目的是什么?另外,在异常处理程序中,您要创建的文件player + '.txt'与最初要写入的文件不同。
Markku K.

@MarkkuK我从stackoverflow的另一个问题中获取了该信息,在这里您检查文件是否存在。所以with open(player):检查文件是否存在,至少我如此认为。我看到的是Okey,只是以为我必须使用“ .txt”将该文件转换为文本文件。
Bondenn 2013年

1
在任何情况下,您都可以使用open(whatever,'a') as highscore:,它将执行您想要的操作:如果文件不存在,则创建该文件;如果文件不存在,则添加至该文件
Markku K.

@MarkkuK天哪,您是对的,因为它的简单性而不得不爱python。谢谢!
Bondenn 2013年

Answers:


50

我不清楚您感兴趣的高分确切存储在哪里,但是下面的代码应该是检查文件是否存在并根据需要追加到文件中的代码。与“ 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()

14
这不是容易出现比赛状况吗?
user541686 '17

24
为什么不只使用模式“ a +”打开它?
埃里克·德·科迪斯

27
如果我们只是使用open(filename, 'a'),还会创建文件(如果不存在)并追加(如果存在)。
Abolfazl

@EricdesCourtis“ a”和“ a +”将不允许您寻求任意偏移(仅到文件末尾)。
naktinis

2
与“ try / except”相比,我更喜欢这种方法。个人偏好是否比在Python中通常认为EAFP风格更好的事实更重要?
AMC

84

您是否尝试过模式“ a +”?

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

但是请注意,f.tell()在Python 2.x中它将返回0。有关详细信息,请参见https://bugs.python.org/issue22651


1
支持,尽管您需要在此建议前面加上“如果您不关心f.tell()”报告的值。
personal_cloud

1
我在此担心a+文档的可移植性:on some Unix systems means that all writes append to the end of the file regardless of the current seek position
贾罗德·史密斯

@JarrodSmith并非IMO真正关心的问题。来自docs:'a' for appending (which on some Unix systems means that all writes append to the end of the file regardless of the current seek position).我认为这对大多数文件使用都是很好的(例如,始终附加)。如果您需要查找特定的偏移量,那么您可能永远不会以这种方式打开文件。
Eric des Courtis

1
我已经在python 2.7.15上和mac os high sierra上都尝试过aa+并且都附加到文件末尾,并且f.tell()两者都报告相同(不为0)。链接的错误也具有一些可移植的解决方法,例如,将查找位置手动设置到文件的末尾,或者改用io不包含该错误的模块。
达沃斯

为什么a+什么时候可以a呢?
Mateen Ulhaq

23

只需在'a'模式下打开它:

a   开放写作。如果文件不存在,则创建该文件。流位于文件的末尾。

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

要查看您是否正在写入新文件,请检查流的位置。如果为零,则文件为空或为新文件。

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

如果您仍在使用Python 2,要解决该错误,请在f.seek(0, os.SEEK_END)其后添加open或使用io.open


2

请注意,如果文件的父文件夹不存在,则会出现相同的错误:

IOError:[Errno 2]没有这样的文件或目录:

下面是处理这种情况的另一种解决方案:
(*)我用sys.stdoutprint不是f.write仅仅显示另一个用例

# 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")

内部print_to_log_file仅负责文件级别的地方:

# 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

请考虑以下状态:

'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

在您的情况下,我将使用其他方法,而只需使用'a''a+'


0

使用pathlib模块(python的面向对象的文件系统路径

仅此而已,这也许是该解决方案的最新pythonic版本。

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}')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.