在 Python 2 中搜索 FileNotFoundError 的等效项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21367320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Searching for equivalent of FileNotFoundError in Python 2
提问by Walle Cyril
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
我创建了一个名为 Options 的类。它工作正常,但不适用于 Python 2。我希望它同时适用于 Python 2 和 3。问题已确定:FileNotFoundError 在 Python 2 中不存在。但如果我使用 IOError,它在 Python 3 中不起作用
Changed in version 3.3: EnvironmentError, IOError, WindowsError, VMSError, socket.error, select.error and mmap.error have been merged into OSError.
在 3.3 版更改:EnvironmentError、IOError、WindowsError、VMSError、socket.error、select.error 和 mmap.error 已合并到 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())
采纳答案by dawg
You can use the base class exception EnvironmentErrorand use the 'errno' attribute to figure out which exception was raised:
您可以使用基类异常EnvironmentError并使用 'errno' 属性来确定引发了哪个异常:
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:
或者以同样的方式使用 IOError :
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.
这适用于 Python 2 或 Python 3。
Be careful not to compare against number values directly, because they can be differenton different platforms. Instead, use the named constants in Python's standard library errnomodulewhich will use the correct values for the run-time platform.
要小心,不要直接比较反对数值,因为它们可以是不同的不同的平台。相反,使用Python 标准库errno模块中的命名常量,它将为运行时平台使用正确的值。
回答by kindall
If FileNotFoundErrorisn't there, define it:
如果FileNotFoundError不存在,请定义它:
try:
FileNotFoundError
except NameError:
FileNotFoundError = IOError
Now you can catch FileNotFoundErrorin Python 2 since it's really IOError.
现在您可以FileNotFoundError使用 Python 2 了,因为它确实是IOError.
Be careful though, IOErrorhas other meanings. In particular, any message should probably say "file could not be read" rather than "file not found."
不过要小心,IOError还有其他含义。特别是,任何消息都应该说“无法读取文件”而不是“找不到文件”。
回答by RayLuo
For what it's worth, although the IOErroris hardly mentioned in Python 3's official documentand does not even showed up in its official Exception hierarchy, it is still there, and it is the parent class of FileNotFoundErrorin Python 3. See python3 -c "print(isinstance(FileNotFoundError(), IOError))"giving you a True. Therefore, you can technically write your code in this way, which works for both Python 2 and Python 3.
值得一提的IOError是,虽然Python 3 的官方文档中几乎没有提到 ,甚至没有出现在其官方的 Exception 层次结构中,但它仍然存在,并且它是FileNotFoundErrorPython 3 中的父类。请参阅python3 -c "print(isinstance(FileNotFoundError(), IOError))"给你一个True. 因此,您可以在技术上以这种方式编写代码,这对 Python 2 和 Python 3 都适用。
try:
content = open("somefile.txt").read()
except IOError: # Works in both Python 2 & 3
print("Oops, we can not read this file")
It might be "good enough" in many cases. Although in general, it is not recommended to rely on an undocumented behavior. So, I'm not really suggesting this approach. I personally use Kindall's answer.
在许多情况下,它可能“足够好”。虽然一般来说,不建议依赖无证行为。所以,我并不是真的建议这种方法。我个人使用Kindall 的回答。
回答by leafmeal
The Python 2 / 3 compatible way to except a FileNotFoundErroris this:
除了 a 的 Python 2 / 3 兼容方式FileNotFoundError是这样的:
import errno
try:
with open('some_file_that_does_not_exist', 'r'):
pass
except EnvironmentError as e:
if e.errno != errno.ENOENT:
raise
Other answers are close, but don't re-raise if the error number doesn't match.
其他答案很接近,但如果错误编号不匹配,请不要重新提出。
Using IOErroris fine for most cases, but for some reason os.listdir()and friends raise OSErrorinstead on Python 2. Since IOErrorinherits from OSErrorit's fine to just always catch OSErrorand check the error number.
IOError在大多数情况下使用是很好的,但出于某种原因os.listdir(),朋友们OSError在 Python 2 上改用了。因为IOError继承自OSError它,所以总是捕获OSError并检查错误号就可以了。
Edit: The previous sentence is only true on Python 3. To be cross compatible, instead catch EnvironmentErrorand check the error number.
编辑:上一句仅适用于 Python 3。为了交叉兼容,改为捕获EnvironmentError并检查错误号。

