如果新文件不存在则写入新文件,如果存在则追加到文件
Posted
技术标签:
【中文标题】如果新文件不存在则写入新文件,如果存在则追加到文件【英文标题】:Writing to a new file if it doesn't exist, and appending to a file if it does 【发布时间】:2013-12-24 08:04:19 【问题描述】:我有一个程序将用户的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'
与您最初尝试写入的文件不同。
@MarkkuK 我是从*** 的另一个问题中得出的,您可以在其中检查文件是否存在。所以 with open(player): 检查文件是否存在,至少我是这么认为的。好吧,我明白了,我只是想我必须使用“.txt”才能使文件成为文本文件。
在任何情况下,你都可以使用open(whatever,'a') as highscore:
,它会做你想做的事情:如果文件不存在则创建,如果存在则追加到它
@MarkkuK 天哪,你是对的,因为它的简单性而爱上 python。谢谢!
【参考方案1】:
你试过'a+'模式吗?
with open(filename, 'a+') as f:
f.write(...)
但请注意,f.tell()
在 Python 2.x 中将返回 0。详情请见https://bugs.python.org/issue22651。
【讨论】:
赞成,但您需要在此建议前加上“如果您不关心f.tell()
报告的值”。
我担心a+
的可移植性,因为在文档中:on some Unix systems means that all writes append to the end of the file regardless of the current seek position
。
@JarrodSmith IMO 不是一个真正的问题。来自文档:'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).
我认为这对于文件的大多数用途都很好(例如,总是附加)。如果你需要寻找特定的偏移量,那么你可能不会以这种方式打开文件。
我已经在 python 2.7.15 的 mac os high sierra 上尝试了 a
和 a+
并且都附加到文件的末尾,f.tell()
在两者中都报告了相同的(不是 0)。链接的错误也有一些可移植的解决方法,例如手动将查找位置设置为文件末尾,或者使用没有该错误的io
模块。
当你只能a
时为什么要a+
?【参考方案2】:
我不清楚您感兴趣的高分的确切存储位置,但下面的代码应该是您需要检查文件是否存在并在需要时附加到它的代码。我更喜欢这种方法而不是“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()
【讨论】:
这不是容易出现竞争条件吗? 为什么不直接用“a+”模式打开呢? 如果我们只使用open(filename, 'a')
,它也会创建文件,如果不存在,如果存在则追加。
我更喜欢这种方法而不是“try/except”。个人偏好是否比EAFP 风格在 Python 中通常被认为更好这一事实更重要?跨度>
@jdhao 这在 Python 3 中可能是真的,但是当被问到问题时,Python 2 很常见【参考方案3】:
只需在'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,要解决the bug,请在open
之后添加f.seek(0, os.SEEK_END)
或改用io.open
。
【讨论】:
【参考方案4】:请注意,如果文件的父文件夹不存在,您将收到相同的错误:
IOError: [Errno 2] 没有这样的文件或目录:
以下是处理这种情况的另一种解决方案:
(*) 我使用 sys.stdout
和 print
而不是 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+'
。
【讨论】:
【参考方案5】:使用pathlib
模块(python 的object-oriented filesystem paths)
只是为了好玩,这可能是解决方案的最新 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')
【讨论】:
与其他答案相比,这个答案很干净而且相对较新。 @ohailolcat - 究竟是什么让它更符合 Python 风格?并不是说这不是pythonic,但它也确实需要导入一个新模块。为什么不只是“a+”?以上是关于如果新文件不存在则写入新文件,如果存在则追加到文件的主要内容,如果未能解决你的问题,请参考以下文章