Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Searching for equivalent of FileNotFoundError in Python 2

I created a class named Options. It works fine but not not with Python 2. And I want it to work on both Python 2 and 3. The problem is identified: FileNotFoundError doesn t exist in Python 2. But if I use IOError it doesn t work in Python 3

Changed in version 3.3: EnvironmentError, IOError, WindowsError, VMSError, socket.error, select.error and mmap.error have been merged into OSError.

What should I do ???(Please do not discuss my choice of portability, I have reasons.)

Here s the code:

#!/usr/bin/python
#-*-coding:utf-8*

#option_controller.py

#Walle Cyril
#25/01/2014

import json
import os

class Options():
    """Options is a class designed to read, add and change informations in a JSON file with a dictionnary in it.

    The entire object works even if the file is missing since it re-creates it.
    If present it must respect the JSON format: e.g. keys must be strings and so on.
    If something corrupted the file, just destroy the file or call read_file method to remake it."""

    def __init__(self,directory_name="Cache",file_name="options.json",imported_default_values=None):
        #json file
        self.option_file_path=os.path.join(directory_name,file_name)
        self.directory_name=directory_name
        self.file_name=file_name
        #self.parameters_json_file={'sort_keys':True, 'indent':4, 'separators':(',',':')}
        #the default data
        if imported_default_values is None:
            DEFAULT_INDENT = 2
            self.default_values={\
                "translate_html_level": 1,\
                "indent_size":DEFAULT_INDENT,\
                "document_title":"Titre"}
        else:
            self.default_values=imported_default_values


    def read_file(self,read_this_key_only=False):
        """returns the value for the given key or a dictionary if the key is not given.

        returns None if it s impossible"""
        try:
            text_in_file=open(self.option_file_path,'r').read()
        except FileNotFoundError:#not 2.X compatible
            text_in_file=""#if the file is not there we re-make one with default values
        if text_in_file=="":#same if the file is empty
            self.__insert_all_default_values()
            text_in_file=open(self.option_file_path,'r').read()

        try:
            option_dict=json.loads(text_in_file)
        except ValueError:
            #if the json file is broken we re-make one with default values
            self.__insert_all_default_values()
            text_in_file=open(self.option_file_path,'r').read()
            option_dict=json.loads(text_in_file)

        if read_this_key_only:
            if read_this_key_only in option_dict:
                return option_dict[read_this_key_only]#
            else:
                #if the value is not there it should be written for the next time
                if read_this_key_only in self.default_values:
                    self.add_option_to_file(read_this_key_only,self.default_values[read_this_key_only])
                    return self.default_values[read_this_key_only]
                else:
                    #impossible because there is not default value so the value isn t meant to be here
                    return None
        else:
            return option_dict

    def add_option_to_file(self,key,value):#or update
        """Adds or updates an option(key and value) to the json file if the option exists in the default_values of the object."""

        option_dict=self.read_file()
        if key in self.default_values:
            option_dict[key]=value
        open(self.option_file_path,'w').write(\
            json.dumps(option_dict,sort_keys=True, indent=4, separators=(',',':')))


    def __insert_all_default_values(self):
        """Recreate json file with default values.

    called if the document is empty or non-existing or corrupted."""
        try:
            open(self.option_file_path,'w').write(\
            json.dumps(self.default_values,sort_keys=True, indent=4, separators=(',',':')))
        except FileNotFoundError:
            os.mkdir(self.directory_name)#Create the directory
            if os.path.isdir(self.directory_name):#succes
                self.__insert_all_default_values()
            else:
                print("Impossible to write in %s and file %s not found" % (os.getcwd(),self.option_file_path))


#demo
if __name__ == '__main__':

    option_file_object=Options()
    print(option_file_object.__doc__)
    print(option_file_object.read_file())
    option_file_object.add_option_to_file("","test")#this should have no effect

    option_file_object.add_option_to_file("translate_html_level","0")#this should have an effect
    print("value of translate_html_level:",option_file_object.read_file("translate_html_level"))
    print(option_file_object.read_file())
like image 692
Walle Cyril Avatar asked Jan 26 '14 18:01

Walle Cyril


2 Answers

If FileNotFoundError isn't there, define it:

try:
    FileNotFoundError
except NameError:
    FileNotFoundError = IOError

Now you can catch FileNotFoundError in Python 2 since it's really IOError.

Be careful though, IOError has other meanings. In particular, any message should probably say "file could not be read" rather than "file not found."

like image 120
kindall Avatar answered Oct 10 '22 06:10

kindall


You can use the base class exception EnvironmentError and use the 'errno' attribute to figure out which exception was raised:

from __future__ import print_function

import os
import errno

try:
    open('no file of this name')   # generate 'file not found error'
except EnvironmentError as e:      # OSError or IOError...
    print(os.strerror(e.errno))  

Or just use IOError in the same way:

try:
    open('/Users/test/Documents/test')   # will be a permission error
except IOError as e:
    print(os.strerror(e.errno))  

That works on Python 2 or Python 3.

Be careful not to compare against number values directly, because they can be different on different platforms. Instead, use the named constants in Python's standard library errno module which will use the correct values for the run-time platform.

like image 30
dawg Avatar answered Oct 10 '22 06:10

dawg