Repository: pandas-dev/pandas

Issue:
Replace bare excepts by explicit excepts in pandas/io/pytables
(superseeds #18419, same task for different files: #22872, #22873, #22875, #22877)

In several parts of the code, we have bare excepts in the form of:
```python
try:
    my_value = my_dict[my_key]
except:  # we are capturing all the exceptions, when we want to capture only KeyError
    my_value = None
```

This is a bad practice, and we want to avoid having this in the code. What we want instead is:
```python
try:
    my_value = my_dict[my_key]
except KeyError:
    my_value = None
```
Of course in every case, the exception can be different (not always `KeyError`), and some research is needed to see which is the right exception (or exceptions, it can be a tuple) that needs to be captured. In some cases, every exception needs to be captured and we'll use `except Exception:`, but this should be avoided unless we really need to capture all exceptions.

This issue is to fix all the bare excepts in testing files `pandas/tests/`. At the moment they are (note that the list can change as code evolves):
```
pandas/io/pytables.py:261:9: E722 do not use bare except'
pandas/io/pytables.py:398:5: E722 do not use bare except'
pandas/io/pytables.py:402:9: E722 do not use bare except'
pandas/io/pytables.py:520:9: E722 do not use bare except'
pandas/io/pytables.py:678:17: E722 do not use bare except'
pandas/io/pytables.py:1164:9: E722 do not use bare except'
pandas/io/pytables.py:1273:9: E722 do not use bare except'
pandas/io/pytables.py:1310:17: E722 do not use bare except'
pandas/io/pytables.py:1321:13: E722 do not use bare except'
pandas/io/pytables.py:1357:17: E722 do not use bare except'
pandas/io/pytables.py:1362:9: E722 do not use bare except'
pandas/io/pytables.py:1627:9: E722 do not use bare except'
pandas/io/pytables.py:1659:9: E722 do not use bare except'
pandas/io/pytables.py:1872:9: E722 do not use bare except'
pandas/io/pytables.py:2235:17: E722 do not use bare except'
pandas/io/pytables.py:2328:9: E722 do not use bare except'
pandas/io/pytables.py:2772:17: E722 do not use bare except'
pandas/io/pytables.py:2846:9: E722 do not use bare except'
pandas/io/pytables.py:2964:9: E722 do not use bare except'
pandas/io/pytables.py:3498:13: E722 do not use bare except'
pandas/io/pytables.py:3617:17: E722 do not use bare except'
pandas/io/pytables.py:3645:17: E722 do not use bare except'
pandas/io/pytables.py:4463:5: E722 do not use bare except'
pandas/io/pytables.py:4785:13: E722 do not use bare except'
```
An updated list can be obtained by running: `flake8 --select=E722 --config=none pandas/io/pytables/`


Discussion:
can u reference the other issue

yes, I'm creating various issues, when I finish I'll cross-reference all them
I'll do this one too while the other one is in review

Resolving patch:
diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py
--- a/pandas/io/pytables.py
+++ b/pandas/io/pytables.py
@@ -258,7 +258,7 @@ def _tables():
         try:
             _table_file_open_policy_is_strict = (
                 tables.file._FILE_OPEN_POLICY == 'strict')
-        except:
+        except AttributeError:
             pass
 
     return _table_mod
@@ -395,11 +395,11 @@ def read_hdf(path_or_buf, key=None, mode='r', **kwargs):
                                      'contains multiple datasets.')
             key = candidate_only_group._v_pathname
         return store.select(key, auto_close=auto_close, **kwargs)
-    except:
+    except (ValueError, TypeError):
         # if there is an error, close the store
         try:
             store.close()
-        except:
+        except AttributeError:
             pass
 
         raise
@@ -517,7 +517,7 @@ def __getattr__(self, name):
         """ allow attribute access to get stores """
         try:
             return self.get(name)
-        except:
+        except (KeyError, ClosedFileError):
             pass
         raise AttributeError("'%s' object has no attribute '%s'" %
                              (type(self).__name__, name))
@@ -675,7 +675,7 @@ def flush(self, fsync=False):
             if fsync:
                 try:
                     os.fsync(self._handle.fileno())
-                except:
+                except OSError:
                     pass
 
     def get(self, key):
@@ -1161,7 +1161,7 @@ def get_node(self, key):
             if not key.startswith('/'):
                 key = '/' + key
             return self._handle.get_node(self.root, key)
-        except:
+        except _table_mod.exceptions.NoSuchNodeError:
             return None
 
     def get_storer(self, key):
@@ -1270,7 +1270,7 @@ def _validate_format(self, format, kwargs):
         # validate
         try:
             kwargs['format'] = _FORMAT_MAP[format.lower()]
-        except:
+        except KeyError:
             raise TypeError("invalid HDFStore format specified [{0}]"
                             .format(format))
 
@@ -1307,7 +1307,7 @@ def error(t):
 
                 try:
                     pt = _TYPE_MAP[type(value)]
-                except:
+                except KeyError:
                     error('_TYPE_MAP')
 
                 # we are actually a table
@@ -1318,7 +1318,7 @@ def error(t):
         if u('table') not in pt:
             try:
                 return globals()[_STORER_MAP[pt]](self, group, **kwargs)
-            except:
+            except KeyError:
                 error('_STORER_MAP')
 
         # existing node (and must be a table)
@@ -1354,12 +1354,12 @@ def error(t):
                     fields = group.table._v_attrs.fields
                     if len(fields) == 1 and fields[0] == u('value'):
                         tt = u('legacy_frame')
-                except:
+                except IndexError:
                     pass
 
         try:
             return globals()[_TABLE_MAP[tt]](self, group, **kwargs)
-        except:
+        except KeyError:
             error('_TABLE_MAP')
 
     def _write_to_group(self, key, value, format, index=True, append=False,
@@ -1624,7 +1624,7 @@ def is_indexed(self):
         """ return whether I am an indexed column """
         try:
             return getattr(self.table.cols, self.cname).is_indexed
-        except:
+        except AttributeError:
             False
 
     def copy(self):
@@ -1654,9 +1654,10 @@ def convert(self, values, nan_rep, encoding, errors):
             kwargs['freq'] = _ensure_decoded(self.freq)
         if self.index_name is not None:
             kwargs['name'] = _ensure_decoded(self.index_name)
+        # making an Index instance could throw a number of different errors
         try:
             self.values = Index(values, **kwargs)
-        except:
+        except Exception:  # noqa: E722
 
             # if the output freq is different that what we recorded,
             # it should be None (see also 'doc example part 2')
@@ -1869,7 +1870,7 @@ def create_for_block(
                 m = re.search(r"values_block_(\d+)", name)
                 if m:
                     name = "values_%s" % m.groups()[0]
-        except:
+        except IndexError:
             pass
 
         return cls(name=name, cname=cname, **kwargs)
@@ -2232,7 +2233,7 @@ def convert(self, values, nan_rep, encoding, errors):
 
                 try:
                     self.data = self.data.astype(dtype, copy=False)
-                except:
+                except TypeError:
                     self.data = self.data.astype('O', copy=False)
 
         # convert nans / decode
@@ -2325,7 +2326,7 @@ def set_version(self):
             self.version = tuple(int(x) for x in version.split('.'))
             if len(self.version) == 2:
                 self.version = self.version + (0,)
-        except:
+        except AttributeError:
             self.version = (0, 0, 0)
 
     @property
@@ -2769,7 +2770,7 @@ def write_array(self, key, value, items=None):
             else:
                 try:
                     items = list(items)
-                except:
+                except TypeError:
                     pass
                 ws = performance_doc % (inferred_type, key, items)
                 warnings.warn(ws, PerformanceWarning, stacklevel=7)
@@ -2843,7 +2844,7 @@ class SeriesFixed(GenericFixed):
     def shape(self):
         try:
             return len(getattr(self.group, 'values')),
-        except:
+        except (TypeError, AttributeError):
             return None
 
     def read(self, **kwargs):
@@ -2961,7 +2962,7 @@ def shape(self):
                 shape = shape[::-1]
 
             return shape
-        except:
+        except AttributeError:
             return None
 
     def read(self, start=None, stop=None, **kwargs):
@@ -3495,7 +3496,7 @@ def create_axes(self, axes, obj, validate=True, nan_rep=None,
         if axes is None:
             try:
                 axes = _AXES_MAP[type(obj)]
-            except:
+            except KeyError:
                 raise TypeError("cannot properly create the storer for: "
                                 "[group->%s,value->%s]"
                                 % (self.group._v_name, type(obj)))
@@ -3614,7 +3615,7 @@ def get_blk_items(mgr, blocks):
                     b, b_items = by_items.pop(items)
                     new_blocks.append(b)
                     new_blk_items.append(b_items)
-                except:
+                except (IndexError, KeyError):
                     raise ValueError(
                         "cannot match existing table structure for [%s] on "
                         "appending data" % ','.join(pprint_thing(item) for
@@ -3642,7 +3643,7 @@ def get_blk_items(mgr, blocks):
             if existing_table is not None and validate:
                 try:
                     existing_col = existing_table.values_axes[i]
-                except:
+                except (IndexError, KeyError):
                     raise ValueError("Incompatible appended table [%s] with "
                                      "existing table [%s]"
                                      % (blocks, existing_table.values_axes))
@@ -4460,7 +4461,7 @@ def _get_info(info, name):
     """ get/create the info for this name """
     try:
         idx = info[name]
-    except:
+    except KeyError:
         idx = info[name] = dict()
     return idx
 
@@ -4782,7 +4783,7 @@ def __init__(self, table, where=None, start=None, stop=None, **kwargs):
                             )
                         self.coordinates = where
 
-            except:
+            except ValueError:
                 pass
 
         if self.coordinates is None:


Test patch: