Skip to content

Commit

Permalink
Fix ResourceWarning from unclosed detached data NRRD files (#90)
Browse files Browse the repository at this point in the history
Enable all warnings during tests to see additional problems in the code. The following warning appeared:
```
ResourceWarning: unclosed file <_io.BufferedReader name='<PYNRRD_DIR>\\nrrd\\tests\\data\\BallBinary30x30x30.raw'>
  tb.tb_frame.clear()
```

Problem resolved by closing the file handle before raising errors. The only time this issue occurs is when the data is detached from the header. The detached data filename is loaded using an `open` call without a "with" block.
  • Loading branch information
addisonElliott authored Apr 2, 2019
1 parent bc5b7ee commit 204b7df
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
18 changes: 15 additions & 3 deletions nrrd/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ def read_data(header, fh=None, filename=None):
data_filename = os.path.join(os.path.dirname(filename), data_filename)

# Override the fh parameter with the data filename
# Note that this is opened without a "with" block, thus it must be closed manually in all circumstances
fh = open(data_filename, 'rb')

# Get the total number of data points by multiplying the size of each dimension together
Expand All @@ -368,10 +369,18 @@ def read_data(header, fh=None, filename=None):
for _ in range(line_skip):
fh.readline()
else:
# Must close the file because if the file was opened above from detached filename, there is no "with" block to
# close it for us
fh.close()

raise NRRDError('Invalid lineskip, allowed values are greater than or equal to 0')

# Skip the requested number of bytes or seek backward, and then parse the data using NumPy
if byte_skip < -1:
# Must close the file because if the file was opened above from detached filename, there is no "with" block to
# close it for us
fh.close()

raise NRRDError('Invalid byteskip, allowed values are greater than or equal to -1')
elif byte_skip >= 0:
fh.seek(byte_skip, os.SEEK_CUR)
Expand All @@ -394,6 +403,10 @@ def read_data(header, fh=None, filename=None):
elif header['encoding'] in ['bzip2', 'bz2']:
decompobj = bz2.BZ2Decompressor()
else:
# Must close the file because if the file was opened above from detached filename, there is no "with" block
# to close it for us
fh.close()

raise NRRDError('Unsupported encoding: "%s"' % header['encoding'])

# Loop through the file and read a chunk at a time (see _READ_CHUNKSIZE why it is read in chunks)
Expand All @@ -412,8 +425,7 @@ def read_data(header, fh=None, filename=None):
# NumPy
data = np.fromstring(decompressed_data[byte_skip:], dtype)

# Close the file
# Even if opened using with keyword, closing it does not hurt
# Close the file, even if opened using "with" block, closing it manually does not hurt
fh.close()

if total_data_points != data.size:
Expand Down Expand Up @@ -457,4 +469,4 @@ def read(filename, custom_field_map=None):
header = read_header(fh, custom_field_map)
data = read_data(header, fh, filename)

return data, header
return data, header
4 changes: 4 additions & 0 deletions nrrd/tests/util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import os
import unittest
import warnings

# Enable all warnings
warnings.simplefilter("always")

DATA_DIR_PATH = os.path.join(os.path.dirname(__file__), 'data')
RAW_NRRD_FILE_PATH = os.path.join(DATA_DIR_PATH, 'BallBinary30x30x30.nrrd')
Expand Down

0 comments on commit 204b7df

Please sign in to comment.