I need to write data to a file and overwrite it if file exists. In case of an error my code should catch an exception and restore original file (if applicable)
How can I restore file? Should I read original one and put content i.e. in a list and then in case of an exception just write this list to a file?
Are there any other options? Many thanks if anyone can provide some kind of an example
Cheers
The code below will make a copy of the original file and set a flag indicating if it existed before or not. Do you code in the try and if it makes it to the end it will set the worked flag to True and your are go to go otherwise, it will never get there, the exception will still be raised but the finally will clean up and replace the file if it had existed in the first place.
import os
import shutil
if os.path.isfile(original_file):
shutil.copy2(original_file, 'temp' + original_file)
prev_existed = True
else:
prev_existed = False
worked = False
try:
with open(original_file, 'w') as f:
## your code
worked = True
except:
raise
finally:
if not worked and prev_existed:
shutil.copy2('temp' + original_file, original_file)
Any attempt to restore on error will be fragile; what if your program can't continue or encounters another error when attempting to restore the data?
A better solution would be to not replace the original file until you know that whatever you're doing succeeded. Write whatever you need to to a temporary file, then when you're ready, replace the original with the temporary.
One way to do it is the append the new data at the end of the existing file. If you catch an error , delete all that you appended.
If no errors, delete everything that you had before appending so the new file will have only the appended data.
Create a copy of your file before starting capturing the data in a new file.
Related
I have a file in my python folder called data.txt and i have another file read.py trying to read text from data.txt but when i change something in data.txt my read doesn't show anything new i put
Something else i tried wasn't working and i found something that read, but when i changed it to something that was actually meaningful it didn't print the new text.
Can someone explain why it doesn't refresh, or what i need to do to fix it?
with open("data.txt") as f:
file_content = f.read().rstrip("\n")
print(file_content)
First and foremost, strings are immutable in Python - once you use file.read(), that returned object cannot change.
That being said, you must re-read the file at any given point the file contents may change.
For example
read.py
def get_contents(filepath):
with open(filepath) as f:
return f.read().rstrip("\n")
main.py
from read import get_contents
import time
print(get_contents("data.txt"))
time.sleep(30)
# .. change file somehow
print(get_contents("data.txt"))
Now, you could setup an infinite loop that watches the file's last modification timestamp from the OS, then always have the latest changes, but that seems like a waste of resources unless you have a specific need for that (e.g. tailing a log file), however there are arguably better tools for that
It was unclear from your question if you do the read once or multiple times. So here are steps to do:
Make sure you call the read function repeatedly with a certain interval
Check if you actually save file after modification
Make sure there are no file usage conflicts
So here is a description of each step:
When you read a file the way you shared it gets closed, meaning it is read only once, you need to read it multiple times if you want to see changes, so make it with some kind of interval in another thread or async or whatever suits your application best.
This step is obvious, remember to hit ctrl+c
It may happen that a single file is being accessed by multiple processes, for example your editor and the script, now to prevent errors try the following code:
def read_file(file_name: str):
while True:
try:
with open(file_name) as f:
return f.read().rstrip("\n")
except IOError:
pass
I want to rename report.json but it is removing the file instead
import os
from pathlib import Path
import json
path =Path( r'C:\Users\Sajid\Desktop\cuckoo (3)\cuckoo\storage\analyses\3\reports')
filename = os.path.join(path,"report.json")
with open(filename) as json_file:
data=json.load(json_file)
var=(data['target']['file']['md5'])
print(var)
json_file.close()
os.rename(filename,var)
I expect this code to rename the file and not delete it
It's probably not deleting it, but moving it to your working directory (so if you launched your script from C:\Users\Sajid, the file would be there, not in C:\Users\Sajid\Desktop\cuckoo (3)\cuckoo\storage\analyses\3\reports). Edit: Based on your comment, this is definitely what's happening; the first time you ran your code, it moved it to your working directory (with component cuckoo (1), where you probably expected it to go to the one with component cuckoo (3)), the second time it failed because os.rename won't overwrite an existing file on Windows.
Change it to combine the desired target directory with the basename of the file, a la:
var = os.path.join(str(path), os.path.basename(data['target']['file']['md5']))
so it stays in the same directory.
You're also unnecessarily closing the file twice (once explicitly, once implicitly via the with block termination). As it happens, the first one is necessary, but only because you kept the rename inside the with block. The simplest solution is to just remove the extra close, and rename outside the with block (in fact, you don't need it open after the json.load, so you may as well close it then):
with open(filename) as json_file:
data = json.load(json_file)
# Dedent to implicitly close file
var = os.path.join(str(path), os.path.basename(data['target']['file']['md5']))
print(var)
os.rename(filename,var)
As written, you won't replace an existing file (on Windows; on UNIX-like systems, it will); if you want to silently replace the existing file everywhere, use os.replace instead of os.rename.
I create a new text file with f = open('file.txt', 'w'). Then, as I go about to get stuff to write on it, there is a problem and I need to exit without actually writing anything.
However, the file is still created, but empty. Is there a way to keep the file from being saved in case nothing is going to be written on it, or do I have to explicitly delete it in case something goes wrong?
You can use atexit to simulate this behavior, but there's probably a Better Way out there somewhere.
import atexit
def safety_trigger():
try:
os.remove(FILENAME)
except FileNotFoundError:
pass
atexit.register(safety_trigger)
with open(FILENAME,'w') as f:
# do your
# file operations
atexit.unregister(safety_trigger)
This way when your script starts, you set it to automatically delete FILENAME when it ends. Once you're done writing to the file, you tell your script NOT to automatically delete FILENAME when it ends.
You could simply prepare the information for writing first and only perform the saving and such if it makes it through preparation without a hitch.
info_to_write = ""
try:
info_to_write += "something!"
# etc...
if something_went_wrong:
raise Exception
with open("file.txt","w") as f:
f.write(info_to_write)
catch:
print "Nothing written, no file created"
I am a beginner, writing a python script in which I need it to create a file that I can write information to. However, I am having problems getting it to create a new, not previously existing file.
for example, I have:
file = open(coordinates.kml, 'w')
which it proceeds to tell me:
nameerror: name 'coordinates' is not defined.
Of course it isn't defined, I'm trying to make that file.
Everything I read on creating a new file says to take this route, but it simply will not allow me. What am I doing wrong?
I even tried to flat out define it...
file = coordinates.kml
file_open = open(file, 'w')
... and essentially got the same result.
You need to pass coordinates.kml as a string, so place them in quotes (single or double is fine).
file = open("coordinates.kml", "w")
In addition to the above answer,
If you want to create a file in the same path, then no problem or else you need to specify the path as well in the quotes.
But surely opening a file with read permission will throw an error as you are trying to access an nonexistent file.
To be future proof and independent of the platforms you can read and write files in binaries. For example if this is Python on Windows, there could be some alternations done to the end of line. Hence reading and writing in Binary mode should help, using switches "rb" and "wb"
file = open("coordinates.kml", "wb")
And also remember to close the file session, else can throw errors while re running the script.
def FileCheck(fn):
try:
fn=open("TestFile.txt","U")
except IOError:
print "Error: File does not appear to exist."
return 0
I'm trying to make a function that checks to see if a file exists and if doesn't then it should print the error message and return 0 . Why isn't this working???
You'll need to indent the return 0 if you want to return from within the except block.
Also, your argument isn't doing much of anything. Instead of assigning it the filehandle, I assume you want this function to be able to test any file? If not, you don't need any arguments.
def FileCheck(fn):
try:
open(fn, "r")
return 1
except IOError:
print "Error: File does not appear to exist."
return 0
result = FileCheck("testfile")
print result
I think os.path.isfile() is better if you just want to "check" if a file exists since you do not need to actually open the file. Anyway, after open it is a considered best practice to close the file and examples above did not include this.
This is likely because you want to open the file in read mode.
Replace the "U" with "r".
Of course, you can use os.path.isfile('filepath') too.
If you just want to check if a file exists or not, the python os library has solutions for that such as os.path.isfile('TestFile.txt'). OregonTrails answer wouldn't work as you would still need to close the file in the end with a finally block but to do that you must store the file pointer in a variable outside the try and except block which defeats the whole purpose of your solution.