BUG: properly close files opened by parsers · pandas-dev/pandas@4a80521 (original) (raw)

`@@ -92,16 +92,24 @@ def init(self, path_or_buf, index=None, convert_dates=True,

`

92

92

`self._path_or_buf, _, _ = get_filepath_or_buffer(path_or_buf)

`

93

93

`if isinstance(self._path_or_buf, compat.string_types):

`

94

94

`self._path_or_buf = open(self._path_or_buf, 'rb')

`

``

95

`+

self.handle = self._path_or_buf

`

95

96

``

96

97

`self._get_properties()

`

97

98

`self._parse_metadata()

`

98

99

``

``

100

`+

def close(self):

`

``

101

`+

try:

`

``

102

`+

self.handle.close()

`

``

103

`+

except AttributeError:

`

``

104

`+

pass

`

``

105

+

99

106

`def _get_properties(self):

`

100

107

``

101

108

`# Check magic number

`

102

109

`self._path_or_buf.seek(0)

`

103

110

`self._cached_page = self._path_or_buf.read(288)

`

104

111

`if self._cached_page[0:len(const.magic)] != const.magic:

`

``

112

`+

self.close()

`

105

113

`raise ValueError("magic number mismatch (not a SAS file?)")

`

106

114

``

107

115

`# Get alignment information

`

`@@ -175,6 +183,7 @@ def _get_properties(self):

`

175

183

`buf = self._path_or_buf.read(self.header_length - 288)

`

176

184

`self._cached_page += buf

`

177

185

`if len(self._cached_page) != self.header_length:

`

``

186

`+

self.close()

`

178

187

`raise ValueError("The SAS7BDAT file appears to be truncated.")

`

179

188

``

180

189

`self._page_length = self._read_int(const.page_size_offset + align1,

`

`@@ -219,6 +228,7 @@ def _get_properties(self):

`

219

228

`# Read a single float of the given width (4 or 8).

`

220

229

`def _read_float(self, offset, width):

`

221

230

`if width not in (4, 8):

`

``

231

`+

self.close()

`

222

232

`raise ValueError("invalid float width")

`

223

233

`buf = self._read_bytes(offset, width)

`

224

234

`fd = "f" if width == 4 else "d"

`

`@@ -227,6 +237,7 @@ def _read_float(self, offset, width):

`

227

237

`# Read a single signed integer of the given width (1, 2, 4 or 8).

`

228

238

`def _read_int(self, offset, width):

`

229

239

`if width not in (1, 2, 4, 8):

`

``

240

`+

self.close()

`

230

241

`raise ValueError("invalid int width")

`

231

242

`buf = self._read_bytes(offset, width)

`

232

243

`it = {1: "b", 2: "h", 4: "l", 8: "q"}[width]

`

`@@ -238,11 +249,13 @@ def _read_bytes(self, offset, length):

`

238

249

`self._path_or_buf.seek(offset)

`

239

250

`buf = self._path_or_buf.read(length)

`

240

251

`if len(buf) < length:

`

``

252

`+

self.close()

`

241

253

`msg = "Unable to read {:d} bytes from file position {:d}."

`

242

254

`raise ValueError(msg.format(length, offset))

`

243

255

`return buf

`

244

256

`else:

`

245

257

`if offset + length > len(self._cached_page):

`

``

258

`+

self.close()

`

246

259

`raise ValueError("The cached page is too small.")

`

247

260

`return self._cached_page[offset:offset + length]

`

248

261

``

`@@ -253,6 +266,7 @@ def _parse_metadata(self):

`

253

266

`if len(self._cached_page) <= 0:

`

254

267

`break

`

255

268

`if len(self._cached_page) != self._page_length:

`

``

269

`+

self.close()

`

256

270

`raise ValueError(

`

257

271

`"Failed to read a meta data page from the SAS file.")

`

258

272

`done = self._process_page_meta()

`

`@@ -302,6 +316,7 @@ def _get_subheader_index(self, signature, compression, ptype):

`

302

316

`if (self.compression != "") and f1 and f2:

`

303

317

`index = const.index.dataSubheaderIndex

`

304

318

`else:

`

``

319

`+

self.close()

`

305

320

`raise ValueError("Unknown subheader signature")

`

306

321

`return index

`

307

322

``

`@@ -598,6 +613,7 @@ def _read_next_page(self):

`

598

613

`if len(self._cached_page) <= 0:

`

599

614

`return True

`

600

615

`elif len(self._cached_page) != self._page_length:

`

``

616

`+

self.close()

`

601

617

`msg = ("failed to read complete page from file "

`

602

618

`"(read {:d} of {:d} bytes)")

`

603

619

`raise ValueError(msg.format(len(self._cached_page),

`

`@@ -643,6 +659,7 @@ def _chunk_to_dataframe(self):

`

643

659

`rslt.loc[ii, name] = np.nan

`

644

660

`js += 1

`

645

661

`else:

`

``

662

`+

self.close()

`

646

663

`raise ValueError("unknown column type %s" %

`

647

664

`self.column_types[j])

`

648

665

``