如何在 Python 中覆盖文件?
Posted
技术标签:
【中文标题】如何在 Python 中覆盖文件?【英文标题】:How to overwrite a file in Python? 【发布时间】:2013-03-07 15:37:15 【问题描述】:我正在尝试覆盖一个文件。我的回答基于Read and overwrite a file in Python
完成我的代码:
<select class="select compact expandable-list check-list"
ONCHANGE="location = this.options[this.selectedIndex].value;">
<option value="% url envelopes:auto_sort %?sort_by=custom">
Custom order
</option>
<optgroup label="Category">
<option value="% url envelopes:auto_sort %?sort_by=cat_asc">
Ascending order
</option>
<option value="% url envelopes:auto_sort %?sort_by=cat_desc">
Descending order
</option>
</optgroup>
</select>
def auto_sort(request):
sort_by = request.GET.get('sort_by', None)
if sort_by:
temp_path = "0/file.txt".format(settings.SITE_ROOT)
f=open(temp_path,'r+')
text = f.read()
text = re.sub('cat_asc', 'cat_desc', text)
f.seek(0)
f.write(text)
f.truncate()
f.close();
handle=open(temp_path,'w+')
handle.write(sort_by)
handle.close();
return HttpResponseRedirect(reverse('envelopes:editor'))
我当前代码的输出:
当我再次尝试重写为custom
时,该文件包含cat_desc
。它重写为customc
。注意末尾的c
,它必须是custom
。
这是我想要实现的目标:
-
我写在文件上,例如
cat_desc
如果我想再写,例如custom
,cat_desc
必须被删除并替换为custom
。
【问题讨论】:
错误发生在哪一行? docs.python.org/2/library/re.html#re.subre.sub 接受三个字符串参数“模式”/“替换”、“字符串”。第四个参数(您的“文本”参数)必须是指定计数的数字 用re.sub
应该做什么?参数在问题和回溯中的顺序不同!
@gnibbler 抱歉,我现在正在编辑我的代码,只是为了得到准确的输出
@RedBaron 谢谢,我现在更新我的最新答案
【参考方案1】:
新答案 ...
您将text
作为re.sub
的第四个参数传递。这应该是int
Help on function sub in module re:
sub(pattern, repl, string, count=0, flags=0)
Return the string obtained by replacing the leftmost
non-overlapping occurrences of the pattern in string by the
replacement repl. repl can be either a string or a callable;
if a string, backslash escapes in it are processed. If it is
a callable, it's passed the match object and must return
a replacement string to be used.
旧答案...
也许你正在做
from os import open
这是一个不同的(较低级别)打开,您只想使用内置打开(您无需导入任何内容即可使用它)
这是一个错误的例子并得到你的错误信息
>>> from os import open
>>> open("some_path", "r+")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
还要覆盖文件,你需要用“w+”打开。 “r”代表读
【讨论】:
我没有使用from os import open
@catherine,好的。问题与覆盖文件无关,而是您正在使用的 wat re.sub
【参考方案2】:
对于您的新问题:
尝试就地覆盖文件基本上是不可能的,除非您用完全相同长度的新字节字符串替换字节字符串。如果您将'cat_desc'
替换为'cat_asc'
,您最终将得到'cat_ascc'
。
你正在做的事情——以'r+'
模式打开它,读取整个内容,处理它,seek
ing 为 0,然后写入整个内容——确实有效。但这不是做事的最佳方式。
无论如何,您的问题是,在您执行此操作后,您立即以'w+'
模式(截断文件)打开完全相同的路径并写入不同的内容。所以,你写的东西现在都没有了。
解决办法是……不要那样做。我不确定你想做什么,但可能不是。
同时,重写文件的最佳方法是“原子写入临时和重命名”习语。这保证了您永远不会损坏文件,您要么获得新文件,要么仍然拥有旧文件。这也意味着您不必将整个文件保存在内存中。你可以一点一点地去。这很简单……如果您不关心 Windows。它的工作原理是这样的:
with tempfile.NamedTemporaryFile(delete=False) as outfile:
with open(inpath) as infile:
# copy from infile to outfile, changing things as you go
os.rename(outfile.name, inpath)
不幸的是,在 Windows 上进行这项工作非常痛苦。 outfile
仍处于打开状态时,您无法移动它,并且您无法在 with
语句之外访问它,除此之外,您不能仅用 outfile
覆盖 infile
;你必须做一个复杂的洗牌。而且它永远不会是完全原子的,除非您愿意要求 Vista/2008 并直接调用 Win32 API。
【讨论】:
【参考方案3】:根据您修改后的问题,也许这样的事情会更简单
def auto_sort(request):
sort_by = request.GET.get('sort_by', None)
if sort_by:
temp_path = "0/file.txt".format(settings.SITE_ROOT)
#Set new_text to whatever you want based on your logic
new_text = 'custom'
f=open(temp_path,'w')
f.write(new_text)
f.close();
handle=open(temp_path,'w+')
handle.write(sort_by)
handle.close();
return HttpResponseRedirect(reverse('envelopes:editor'))
【讨论】:
我再次收到错误TypeError:an integer is required
。这是之前的错误。
删除 re.sub 部分。你不需要它【参考方案4】:
您的问题与写入文件无关。
回溯告诉你这行是罪魁祸首:
File "/home/cath/src/envelopebudget/envelopebudget/settings/../apps/envelopes/views.py" in auto_sort
357. text = re.sub('cat_desc', 'cat_asc', 'custom', text)
如果你查看re.sub
方法,你就错了:
re.sub(pattern, repl, string, count=0, flags=0)
您将'cat_desc'
作为pattern
传递,'cat_asc'
作为repl
,'custom'
作为string
传递,text
作为count
传递。这没有任何意义。 re.sub
期望 count
是一个整数,而你给了它一个字符串。
【讨论】:
好的,我已经删除了自定义,现在可以使用了。但我想要实现的是完全重写文件。 @catherine:好的,但是如果这不起作用,那么您遇到了一个完全不同的问题,您需要详细告诉我们这是什么,最好是在一个新问题中。 是否允许创建新问题?我的问题是覆盖我作为标题的文件。 是的,允许,甚至鼓励创建一个新问题。这些问题和答案应该对未来有类似问题的搜索者有用。如果您一得到答案就更改问题,则原始问题不再存在,原始答案不再适用于该问题【参考方案5】:你能把完整的错误复制粘贴回去吗
试试:
def auto_sort(request):
sort_by = request.GET.get('sort_by', None)
if sort_by:
temp_path = "0/file.txt".format(settings.SITE_ROOT)
f=open(temp_path,'r')
text = f.read()
text = re.sub('custom', 'cat_asc', 'cat_desc', text)
f.close();
handle=open(temp_path,'w')
handle.write(sort_by)
handle.close();
return HttpResponseRedirect(reverse('envelopes:editor'))
【讨论】:
以上是关于如何在 Python 中覆盖文件?的主要内容,如果未能解决你的问题,请参考以下文章