Skip to content

Commit

Permalink
ipython exit handler to close file handles of stale hdf5 files
Browse files Browse the repository at this point in the history
  • Loading branch information
PhilipDeegan committed Nov 1, 2021
1 parent 7574d0e commit c0c85a0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
55 changes: 55 additions & 0 deletions pyphare/pyphare/core/ipython.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@




import weakref
h5_weak_refs = {}

def clean_dead_h5_weak_refs():
for h5_path, h5_weak_ref in h5_weak_refs.copy().items():
if h5_weak_ref["ref"]() is None:
del h5_weak_refs[h5_path]

# https://stackoverflow.com/a/40222538/795574
try:
def exit_register(fun, *args, **kwargs):
def callback():
fun()
ip.events.unregister('post_execute', callback)
ip.events.register('post_execute', callback)

ip = get_ipython() # should fail if not running under ipython

def add_h5_weak_ref(h5Filepath, h5File):
import pathlib, datetime, time
clean_dead_h5_weak_refs()

h5_weak_refs[h5Filepath] = {
"ref": weakref.ref(h5File),
"access": int(time.time()),
"path": pathlib.Path(h5Filepath)
}

except NameError:

def add_h5_weak_ref(h5Filepath, h5File):
pass # empty function for normal (not jupyter) case

# forwarding import to keep functionality even if ipython is not in use
# it's possible this isn't even needed, and we just want to execute the callback for only if
# we're running under ipython, in that case, "exit_register" -> "ipython_exit_register" and
# replace the next line with def ipython_exit_register(fun, *args, **kwargs): pass
from atexit import register as exit_register # lgtm [py/unused-import]




@exit_register
def close_h5_files_refs():
import pathlib, datetime, time
for h5_weak_ref_dict in list(h5_weak_refs.values()):
h5_ref = h5_weak_ref_dict["ref"]()
if h5_ref is not None:
mtime = int(h5_weak_ref_dict["path"].stat().st_mtime)
if mtime > h5_weak_ref_dict["access"] and h5_ref.__bool__():
h5_ref.close()
5 changes: 4 additions & 1 deletion pyphare/pyphare/pharesee/hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import matplotlib.pyplot as plt
from ..core.phare_utilities import refinement_ratio, deep_copy


from ..core.ipython import add_h5_weak_ref


class PatchData:
Expand Down Expand Up @@ -1108,6 +1108,9 @@ def patch_has_datasets(h5_patch_grp):
def hierarchy_fromh5(h5_filename, time, hier, silent=True):
import h5py
data_file = h5py.File(h5_filename, "r")

# ADD ref only for jupyter to close file handles without killing kernel
add_h5_weak_ref(h5_filename, data_file)
basename = os.path.basename(h5_filename)

root_cell_width = np.asarray(data_file.attrs["cell_width"])
Expand Down

0 comments on commit c0c85a0

Please sign in to comment.