如何覆盖Python中的文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15491417/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:15:19  来源:igfitidea点击:

How to overwrite a file in Python?

pythonfile

提问by catherine

I'm trying to overwrite a file. I based my answer on this Read and overwrite a file in Python

我正在尝试覆盖文件。我的答案基于这个Read and overwrite a file in Python

To complete my codes:

要完成我的代码:

<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'))

The output of my current codes:

我当前代码的输出:

The file contains cat_descwhen I try rewrite again as custom. It rewrites as customc. Notice the cat the end, it must be customonly.

该文件包含cat_desc当我再次改写作为尝试custom。它重写为customc. 注意c最后的,它必须是customonly。

Here is what I'm trying to achieve:

这是我想要实现的目标:

  1. I write on file, for example, cat_desc
  2. If I want to write again, for example custom, the cat_descmust be removed and replaced with custom.
  1. 例如,我写在文件上, cat_desc
  2. 例如custom,如果我想再次写入,则cat_desc必须将其删除并替换为custom

采纳答案by RedBaron

Based on your revised question, maybe something like this would be simpler

根据您修改后的问题,也许这样的事情会更简单

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'))

回答by cbystrek

Can you copy and paste the full error back

你能复制并粘贴完整的错误吗

Try:

尝试:

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'))

回答by John La Rooy

New anwser ...

新的回答...

You're passing textas the 4th parameter of re.sub. This is supposed to be an int

您将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.


old answer ...

旧答案...

Perhaps you are doing

也许你正在做

from os import open

That is a different (lower level) open, you want to just use the builtin open (you don't need to import anything to use it)

这是一个不同的(较低级别的)开放,你只想使用内置的开放(你不需要导入任何东西来使用它)

Here is an example of doing it wrong and getting your error message

这是做错了并获取错误消息的示例

>>> from os import open
>>> open("some_path", "r+")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required

Also to overwrite the file, you need to open with "w+". "r" stands for read

同样要覆盖文件,您需要使用“w+”打开。“r”代表读

回答by abarnert

Your problem has nothing to do with writing a file.

你的问题与写文件无关。

The traceback tells you that this line is the culprit:

回溯告诉你这一行是罪魁祸首:

File "/home/cath/src/envelopebudget/envelopebudget/settings/../apps/envelopes/views.py" in auto_sort
  357.         text = re.sub('cat_desc', 'cat_asc', 'custom', text)

If you look at the re.submethod, you're calling it wrong:

如果你看看这个re.sub方法,你就错了:

re.sub(pattern, repl, string, count=0, flags=0)

You're passing 'cat_desc'as the pattern, 'cat_asc'as the repl, 'custom'as the string, and textas the count. That doesn't make any sense. re.subexpects the countto be an integer, and you've given it a string.

你传递'cat_desc'pattern'cat_asc'因为repl'custom'作为stringtext作为count。那没有任何意义。re.sub期望count是一个整数,而你已经给了它一个字符串。

回答by abarnert

For your new question:

对于您的新问题:

Trying to overwrite a file in-place is basically impossible, unless you're replacing byte strings with new byte strings of the exact same length. If you replace 'cat_desc'with 'cat_asc', you're going to end up with 'cat_ascc'.

尝试就地覆盖文件基本上是不可能的,除非您用完全相同长度的新字节字符串替换字节字符串。如果您替换'cat_desc''cat_asc',你会直到结束'cat_ascc'

What you're doing—opening it in 'r+'mode, reading the whole thing, processing it, seeking to 0, and writing the whole thing—does work. But it's not the best way to do things.

您正在做的事情——以'r+'模式打开它、读取整个内容、处理它、seek归零并写入整个内容——确实有效。但这不是做事的最佳方式。

And at any rate, your problem is that immediately after you do this, you open the exact same path in 'w+'mode (which truncates the file) and write something different. So, whatever you wrote is now gone.

无论如何,您的问题是,在您执行此操作后,您立即以'w+'mode(截断文件)打开完全相同的路径并写入不同的内容。所以,你写的东西现在都不见了。

The solution to that is… don't do that. I'm not sure what you were trying to do, but that probably isn't it.

解决办法是……不要那样做。我不确定你想做什么,但可能不是这样。

Meanwhile, the best way to rewrite a file is the "atomic write temp and rename" idiom. This guarantees that you never corrupt the file, you either get the new file or still have the old one. It also means you don't have to keep the whole file around in memory; you can go bit by bit. And it's very simple… if you don't care about Windows. It works like this:

同时,重写文件的最佳方法是“原子写临时和重命名”习语。这保证您永远不会损坏文件,您要么获得新文件,要么仍然拥有旧文件。这也意味着您不必将整个文件保存在内存中;你可以一点一点地去。它非常简单……如果您不关心 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)

Unfortunately, making this work on Windows is very painful. You can't move outfilewhile it's still open, and you can't access it outside the withstatement, and on top of that you can't just overwrite infilewith outfile; you have to do a complicated shuffle. And it's never going to be completely atomic, unless you're willing to require Vista/2008 and to call Win32 APIs directly.

不幸的是,在 Windows 上进行这项工作非常痛苦。outfile当它仍然打开时你不能移动,你不能在with语句之外访问它,最重要的是你不能infileoutfile;覆盖它。你必须做一个复杂的洗牌。它永远不会是完全原子的,除非您愿意需要 Vista/2008 并直接调用 Win32 API。