简体   繁体   English

如何在Python中覆盖文件?

[英]How to overwrite a file in Python?

I'm trying to overwrite a file. 我正在尝试覆盖文件。 I based my answer on this Read and overwrite a file in Python 我基于此答案在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_desc when I try rewrite again as custom . 当我尝试再次按custom重写时,文件包含cat_desc It rewrites as customc . 它重写为customc Notice the c at the end, it must be custom only. 请注意最后的c ,它只能是custom

Here is what I'm trying to achieve: 这是我要实现的目标:

  1. I write on file, for example, cat_desc 我写在文件上,例如cat_desc
  2. If I want to write again, for example custom , the cat_desc must be removed and replaced with custom . 如果要再次编写,例如custom ,必须删除cat_desc并用custom代替。

New anwser ... 新的安瑟尔...

You're passing text as the 4th parameter of re.sub . 您正在传递text作为re.sub的第四个参数。 This is supposed to be an int 这应该是一个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+". 同样,要覆盖文件,您需要使用“ w +”打开。 "r" stands for read “ r”代表阅读

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, seek ing to 0, and writing the whole thing—does work. 您正在做的事情-在'r+'模式下打开它,读取整个内容,对其进行处理, seek到0,然后编写整个内容-可以正常工作。 But it's not the best way to do things. 但这不是做事情的最佳方法。

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. 无论如何,您的问题是,执行此操作后,立即在'w+'模式(截断文件)中打开了完全相同的路径,并编写了不同的内容。 So, whatever you wrote is now gone. 因此,无论您写什么,现在都消失了。

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. 而且非常简单……如果您不关心Windows。 It works like this: 它是这样的:

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. 不幸的是,在Windows上进行这项工作非常痛苦。 You can't move outfile while it's still open, and you can't access it outside the with statement, and on top of that you can't just overwrite infile with outfile ; 您不能在outfile仍处于打开状态时移动它,也不能在with语句之外访问它,最重要的是,您不能仅使用outfile覆盖infile 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. 除非您愿意要求Vista / 2008并直接调用Win32 API,否则它永远不会是原子的。

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

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.sub method, 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 text as the count . 你传递'cat_desc'pattern'cat_asc'作为repl'custom'string ,而textcount That doesn't make any sense. 那没有任何意义。 re.sub expects the count to be an integer, and you've given it a string. re.sub期望该count为整数,并且已为其指定了字符串。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM