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:
cat_desc
custom
, the cat_desc
must be removed and replaced with custom
.Overwriting a File, Part 1 To edit the settings for a file, locate the file you wish to overwrite and hover over the file name. Click the chevron button that appears to the right of the file name and select Overwrite File from the menu.
Basics of Writing Files in Python Available are two modes, writing to a new file (and overwriting any existing data) and appending data at the end of a file that already exists.
w : Opens in write-only mode. The pointer is placed at the beginning of the file and this will overwrite any existing file with the same name.
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
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, seek
ing 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.
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'))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With