7

I'm trying to overwrite a file. I based my answer on this 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_desc when I try rewrite again as custom. It rewrites as customc. Notice the c at the end, it must be custom only.

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_desc must be removed and replaced with custom.
Community
  • 1
  • 1
catherine
  • 22,492
  • 12
  • 61
  • 85
  • 3
    Which line is the error occurring on? – Serdalis Mar 19 '13 at 04:28
  • http://docs.python.org/2/library/re.html#re.sub re.sub takes three string arguments 'pattern'/ 'replacement','string'. The fourth argument (your "text" argument) has to be a number specifying the count – RedBaron Mar 19 '13 at 04:48
  • What is the line with `re.sub` _supposed_ to do? The parameters are in different orders in the question and the traceback! – John La Rooy Mar 19 '13 at 04:48
  • @gnibbler sorry I'm currently edit my codes now just to get the exact output – catherine Mar 19 '13 at 04:53
  • @RedBaron thanks, I update my answer now for the latest – catherine Mar 19 '13 at 04:56
  • This should work `text = re.sub('cat_desc', 'custom', text)` – John La Rooy Mar 19 '13 at 05:01
  • Could you expand your question. 1. Do you only write "cat_desc" or a whole line say "I am cat_desc"? 2. Your current code replaces cat_asc with cat_desc, "custom" does not come into picture. Maybe you should update the code too? – RedBaron Mar 19 '13 at 05:03
  • @RedBaron only `cat_desc`, `cat_asc`, and `custom`. – catherine Mar 19 '13 at 05:04
  • In that case regular expressions seem a bit of an overkill. Just wipe the file (Open in _w_ mode) and write what you want (You are anyways seeking to 0 to write) – RedBaron Mar 19 '13 at 05:06
  • @RedBaron can you post your answer. I really don't know about this. I just follow what I have search. – catherine Mar 19 '13 at 05:10

5 Answers5

5

New anwser ...

You're passing text as the 4th parameter of re.sub. This is supposed to be an 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

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
5

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

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.

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.

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:

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 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; 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.

abarnert
  • 354,177
  • 51
  • 601
  • 671
4

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'))
RedBaron
  • 4,717
  • 5
  • 41
  • 65
2

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(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. That doesn't make any sense. re.sub expects the count to be an integer, and you've given it a string.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • ok I already erase the custom and it works now. But what I'm trying to achieve is completely rewrite the file. – catherine Mar 19 '13 at 04:47
  • @catherine: OK, but if that's not working, you have a completely different problem, and you'll need to tell us what that is in detail, preferably in a new question. – abarnert Mar 19 '13 at 05:03
  • Is it allow to create new question? My problem is overwrite the file which I put as title. – catherine Mar 19 '13 at 05:09
  • Yes, it's allowed, and even encouraged, to create a new question. These questions and answers are supposed to be useful for future searchers with similar problems. If you change your question as soon as you get an answer, the original question no longer exists, and the original answer no longer applies to the question – abarnert Mar 19 '13 at 05:22
0

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'))
cbystrek
  • 54
  • 2