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. たとえばcustom、もう一度書きたい場合は、 をcat_desc削除して に置き換える必要がありますcustom
4

5 に答える 5

5

新しい質問について:

バイト文字列をまったく同じ長さの新しいバイト文字列に置き換えない限り、ファイルをその場で上書きしようとすることは基本的に不可能です。に置き換える'cat_desc''cat_asc'、 になります'cat_ascc'

モードで開き'r+'、すべてを読み取り、処理し、seek0 に変更し、すべてを書き込むことは機能します。しかし、それは最善の方法ではありません。

とにかく、あなたの問題は、これを行った直後に、'w+'モードでまったく同じパスを開き (ファイルを切り捨てます)、別のものを書き込むことです。だから、あなたが書いたものはすべてなくなりました。

それに対する解決策は… そうしないことです。何をしようとしていたのかわかりませんが、おそらくそうではありません。

一方、ファイルを書き換える最良の方法は、「atomic write temp and rename」イディオムです。これにより、ファイルが破損することはなく、新しいファイルを取得するか、古いファイルを保持していることが保証されます。また、ファイル全体をメモリ内に保持する必要がないことも意味します。あなたは少しずつ行くことができます。それは非常に簡単です... 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'としてstring、として渡してtextいます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 に答える