我正在创建一个程序,它将创建一个文件并将其保存到文件名为sample.xml的目录中.当我尝试再次运行程序时保存文件,它会将旧文件覆盖到新文件中,因为它们具有相同的文件名.如何增加文件名,以便每当我尝试再次运行代码时,它将增加文件名.并且不会覆盖现有的.我正在考虑首先检查目录上的文件名,如果它们是相同的,代码将生成一个新的文件名:
fh = open("sample.xml", "w")
rs = [blockresult]
fh.writelines(rs)
fh.close()
Run Code Online (Sandbox Code Playgroud)
bos*_*ssi 42
我会迭代sample[int].xml例如并获取文件或目录未使用的下一个可用名称.
import os
i = 0
while os.path.exists("sample%s.xml" % i):
i += 1
fh = open("sample%s.xml" % i, "w")
....
Run Code Online (Sandbox Code Playgroud)
那应该先给你sample0.xml,然后是sample1.xml等.
请注意,默认情况下,相对文件表示法与您运行代码的文件目录/文件夹相关.必要时使用绝对路径.使用os.getcwd()读你的当前目录下,并os.chdir(path_to_dir)设置新的当前目录.
Mar*_*oma 10
def get_nonexistant_path(fname_path):
"""
Get the path to a filename which does not exist by incrementing path.
Examples
--------
>>> get_nonexistant_path('/etc/issue')
'/etc/issue-1'
>>> get_nonexistant_path('whatever/1337bla.py')
'whatever/1337bla.py'
"""
if not os.path.exists(fname_path):
return fname_path
filename, file_extension = os.path.splitext(fname_path)
i = 1
new_fname = "{}-{}{}".format(filename, i, file_extension)
while os.path.exists(new_fname):
i += 1
new_fname = "{}-{}{}".format(filename, i, file_extension)
return new_fname
Run Code Online (Sandbox Code Playgroud)
在打开文件之前,请致电
fname = get_nonexistant_path("sample.xml")
Run Code Online (Sandbox Code Playgroud)
这将给你'sample.xml'或 - 如果这个alreay存在 - 'sample-i.xml'其中i是最低的正整数,使得该文件尚不存在.
我推荐使用os.path.abspath("sample.xml").如果您有~主目录,则可能需要先将其展开.
请注意,如果您同时运行多个实例,则此简单代码可能会出现竞争条件.如果这可能是个问题,请检查此问题.
依次检查每个文件名以找到下一个可用的文件名,对于少量文件,效果很好,但是随着文件数量的增加,速度很快变慢。
这是一个在log(n)时间中查找下一个可用文件名的版本:
import os
def next_path(path_pattern):
"""
Finds the next free path in an sequentially named list of files
e.g. path_pattern = 'file-%s.txt':
file-1.txt
file-2.txt
file-3.txt
Runs in log(n) time where n is the number of existing files in sequence
"""
i = 1
# First do an exponential search
while os.path.exists(path_pattern % i):
i = i * 2
# Result lies somewhere in the interval (i/2..i]
# We call this interval (a..b] and narrow it down until a + 1 = b
a, b = (i // 2, i)
while a + 1 < b:
c = (a + b) // 2 # interval midpoint
a, b = (c, b) if os.path.exists(path_pattern % c) else (a, c)
return path_pattern % b
Run Code Online (Sandbox Code Playgroud)
为了衡量速度的提高,我编写了一个小的测试函数,该函数创建了10,000个文件:
for i in range(1,10000):
with open(next_path('file-%s.foo'), 'w'):
pass
Run Code Online (Sandbox Code Playgroud)
并实现了幼稚的方法:
def next_path_naive(path_pattern):
"""
Naive (slow) version of next_path
"""
i = 1
while os.path.exists(path_pattern % i):
i += 1
return path_pattern % i
Run Code Online (Sandbox Code Playgroud)
结果如下:
快速版本:
real 0m2.132s
user 0m0.773s
sys 0m1.312s
Run Code Online (Sandbox Code Playgroud)
天真的版本:
real 2m36.480s
user 1m12.671s
sys 1m22.425s
Run Code Online (Sandbox Code Playgroud)
最后,请注意,如果多个参与者试图同时按顺序创建文件,则这两种方法都容易受到竞争条件的影响。
尝试设置一个count变量,然后递增嵌套在与写入文件相同的循环中的该变量。将count循环包含在文件名中并带有转义字符,因此每个循环都在+1处打勾,因此在文件。
我刚刚完成的项目中的一些代码:
numberLoops = #some limit determined by the user
currentLoop = 1
while currentLoop < numberLoops:
currentLoop = currentLoop + 1
fileName = ("log%d_%d.txt" % (currentLoop, str(now())))
Run Code Online (Sandbox Code Playgroud)
以供参考:
from time import mktime, gmtime
def now():
return mktime(gmtime())
Run Code Online (Sandbox Code Playgroud)
这可能与您的情况无关,但是我正在运行该程序的多个实例并生成大量文件。希望这可以帮助!
有两种方法可以做到这一点:
一种简单的方法是:
import os.path as pth
filename = "myfile"
filenum = 1
while (pth.exists(pth.abspath(filename+str(filenum)+".py")):
filenum+=1
my_next_file = open(filename+str(filenum)+".py",'w')
Run Code Online (Sandbox Code Playgroud)
作为设计的事情,while True会减慢速度,并且对于代码可读性来说并不是一件好事
编辑:@EOL 贡献/想法
所以我认为没有 .format 乍一看更具可读性 - 但使用 .format 更适合通用性和约定。
import os.path as pth
filename = "myfile"
filenum = 1
while (pth.exists(pth.abspath(filename+str(filenum)+".py")):
filenum+=1
my_next_file = open("{}{}.py".format(filename, filenum),'w')
# or
my_next_file = open(filename + "{}.py".format(filenum),'w')
Run Code Online (Sandbox Code Playgroud)
并且您不必使用abspath - 如果您愿意,您可以使用相对路径,有时我更喜欢abs路径,因为它有助于标准化传递的路径:)。
import os.path as pth
filename = "myfile"
filenum = 1
while (pth.exists(filename+str(filenum)+".py"):
filenum+=1
##removed for conciseness
Run Code Online (Sandbox Code Playgroud)