Looping function to ask for input until valid - python

I have this function:
def read_file(fname):
f = open(fname, 'r')
s = f.read()
return s
It is supposed to take an input(the name of the file to read) and save it to a variable called portfolio. However, if I specify a file that does not exist, I get an IOError, and I can't seem to figure out how to deal with it through try/except.
Any ideas?

You can't stop it from giving you the IOError for a nonexistent file. If you could, how would you even know that you had to do anything, like ask for another filename?
What you can do is deal with that error—in any way you want, like asking for another filename.
For example:
while True:
fname = raw_input('Gimme a filename')
try:
contents = read_file(fname)
break
except IOError as e:
print('Sorry, {} gives me an error: {}'.format(fname, e))
Now, when you run this, it'll keep asking for a filename until you give it one that you can read. If you give it a file that doesn't exist (or one that you don't have read permissions for, or that's locked for exclusive access, or that's stored on a bad disk block, or anything else that can cause an error), it'll ask you again.

Why not just do this?
success = 0
while (success == 0):
try:
#get your input
read_file(fname)
success = 1
except(IOError):
success = 0 #totally unnecessary I guess, but whatever
It's been a while since I did real development, so that might not be how try/except actually works in Python, but you get the idea.

Related

Json.load rising "json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)" even with an "anti_empty" condition

I already post about my problem and I thought it was solved, but after a few time the error rise again. I'm gonna explain my program from the beginning.
I got a Json file that contain values permanently update by another program, I want to get an overlay that display those values, that means I got to open and read my json file every second (or more) with the "after()" method. (Im using tkinter for my overlay).
When I run my tkinter window without the other program that update the values, everything work perfectly, I can update manually a value and it will be update on the overlay.
When I run both programs together after an amount of time, I get the empty json error, sometimes after 5 minutes, sometimes after 45 minutes, It's random.
I tried the following issues :
Issue 1 :
def is_json():
with open ('my_json') as my_file :
myjson = my_file.read()
try:
json_object = json.loads(myjson)
except json.JSONDecodeError as e:
return False
return True
if is_json():
with open ('my_json') as my_file:
data = json.load(my_file)
else :
time.sleep(0.1)
Issue 2:
while True:
if os.path.getsize("/my_json") > 0:
with open ('my_json') as my_file :
myjson = my_file.read()
else:
time.sleep(0.2)
I tryed another one, but I dont want to code it again, that was a function that allow one program to read/write on the json only in "even" seconds and the other one can only do it in "odd" second.
I try this to avoid interactions, cause I think that's my problem, but none of those solutions worked.
You should return the parsed JSON in the same function that has the try/except. Otherwise, the file could change between calling is_json() and json.load().
def json_load_retry(filename, sleeptime=0.1):
while True:
with open(filename) as f:
try:
return json.load(f)
except json.JSONDecodeError:
time.sleep(sleeptime)
myjson = json_load_retry('my_json', sleeptime=0.2)

Python script makes a file but doesn't write anything

First, code gets a name and makes a file with w permission (also tested r+) and it should write any other input in file, but it doesn't. I get an empty file.
user_name_in =input("gets Input")
fname = user_name_in
f = input()
ufile = open(fname,"w")
while True:
f=input(answer)
ufile.write(f)
As i wrote in the comments, always use the with block to handle files as it takes care of intricacies you don't have to worry about. Now on the code, you repeat yourself, for example the first two lines are actually one.. This is what it would look when cleaned a bit.
fname = input("gets Input")
with open(fname, "w") as ufile:
f = input('write something')
ufile.write(f)
And as others also noticed, the answer is never declared, there is no termination condition and the input prompts are either not the best or totally absent.
This code works for me:
user_name_in =input("gets Input")
fname = user_name_in
f = input()
ufile = open(fname,"w")
while True:
f=input(answer)
ufile.write(f)
Some considerations:
I don't see where answer is declared, neither python interpreter see :P, maybe you forgot to paste this part of the code or indeed this was the error?
I don't understand why you assign the name of the file to a variable and then re-assign to another one.
How do I stop writing to the file? The only way I found was Ctrl-C, which doesn't sound ideal.
To reassure the file is being closed you can replace it with a with open(fname) as ufile block

Don't save empty file

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"

File Open Function with Try & Except Python 2.7.1

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.

Is there a special trick to downloading a zip file and writing it to disk with Python?

I am FTPing a zip file from a remote FTP site using Python's ftplib. I then attempt to write it to disk. The file write works, however most attempts to open the zip using WinZip or WinRar fail; both apps claim the file is corrupted. Oddly however, when right clicking and attempting to extract the file using WinRar, the file will extract.
So to be clear, the file write will work, but will not open inside the popular zip apps, but will decompress using those same apps. Note that the Python zipfile module never fails to extract the zips.
Here is the code that I'm using to get the zip file from the FTP site (please ignore the bad tabbing, that's not the issue).
filedata = None
def appender(chunk):
global filedata
filedata += chunk
def getfile(filename):
try:
ftp = None
try:
ftp = FTP(address)
ftp.login('user', 'password')
except Exception, e:
print e
command = 'RETR ' + filename
idx = filename.rfind('/')
path = filename[0:idx]
ftp.cwd(path)
fileonly = filename[idx+1:len(filename)]
ftp.retrbinary('RETR ' + filename, appender)
global filedata
data = filedata
ftp.close()
filedata = ''
return data
except Exception, e:
print e
data = getfile('/archives/myfile.zip')
file = open(pathtoNTFileShare, 'wb')
file.write(data)
file.close()
Pass file.write directly inside the retrbinary function instead of passing appender. This will work and it will also not use that much RAM when you are downloading a big file.
If you'd like the data stored inside a variable though, you can also have a variable named:
blocks = []
Then pass to retrbinary instead of appender:
blocks.append
Your current appender function is wrong. += will not work correctly when there is binary data because it will try to do a string append and stop at the first NULL it sees.
As mentioned by #Lee B you can also use urllib2 or Curl. But your current code is almost correct if you make the small modifications I mentioned above.
I've never used that library, but urllib2 works fine, and is more straightforward. Curl is even better.
Looking at your code, I can see a couple of things wrong. Your exception catching only prints the exception, then continues. For fatal errors like not getting an FTP connection, they need to print the message and then exit. Also, your filedata starts off as None, then your appender uses += to add to that, so you're trying to append a string + None, which gives a TypeError when I try it here. I'm surprised it's working at all; I would have guessed that the appender would throw an exception, and so the FTP copy would abort.
While re-reading, I just noticed another answer about use of += on binary data. That could well be it; python tries to be smart sometimes, and could be "helping" when you join strings with whitespace or NULs in them, or something like that. Your best bet there is to have the file open (let's call it outfile), and use your appender to just outfile.write(chunk).

Categories

Resources