7

我正在尝试覆盖文件。我的答案基于这个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'))

我当前代码的输出:

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

这是我想要实现的目标:

  1. 我写在文件上,例如,cat_desc
  2. 如果我想再次写,例如customcat_desc必须删除并替换为custom
4

5 回答 5

5

新答案...

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”代表读

于 2013-03-19T04:26:11.907 回答
5

对于您的新问题:

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

你正在做的事情——以'r+'模式打开它,读取整个内容,处理它,seek设置为 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语句之外访问它,最重要的是你不能infileoutfile;覆盖它。你必须做一个复杂的洗牌。而且它永远不会是完全原子的,除非您愿意要求 Vista/2008 并直接调用 Win32 API。

于 2013-03-19T05:13:35.293 回答
4

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

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'))
于 2013-03-19T05:14:08.137 回答
2

您的问题与写入文件无关。

回溯告诉你这条线是罪魁祸首:

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'作为stringtext作为传递count。这没有任何意义。re.sub期望count是一个整数,并且你给了它一个字符串。

于 2013-03-19T04:45:25.100 回答
0

您可以将完整的错误复制并粘贴回去吗

尝试:

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'))
于 2013-03-19T04:25:42.083 回答