Fix `fs.open` resource leaks
State: closed | Author: tkukurin (CONTRIBUTOR)

Invoking `{load,save}_from_dict` results in resource leak warnings, this should fix.
Introduces no significant logic changes.

Comments: _The documentation is not available anymore as the PR was closed or merged._

@mariosasko Sorry, I didn't check tests/style after doing a merge from the Git UI last week. Thx for fixing. 

FYI I'm getting "Only those with [write access](https://docs.github.com/articles/what-are-the-different-access-permissions) to this repository can merge pull requests." so it seems somebody else needs to merge this.

<details>
<summary>Show benchmarks</summary>

PyArrow==6.0.0

<details>
<summary>Show updated benchmarks!</summary>

### Benchmark: benchmark_array_xd.json

| metric | read_batch_formatted_as_numpy after write_array2d | read_batch_formatted_as_numpy after write_flattened_sequence | read_batch_formatted_as_numpy after write_nested_sequence | read_batch_unformated after write_array2d | read_batch_unformated after write_flattened_sequence | read_batch_unformated after write_nested_sequence | read_col_formatted_as_numpy after write_array2d | read_col_formatted_as_numpy after write_flattened_sequence | read_col_formatted_as_numpy after write_nested_sequence | read_col_unformated after write_array2d | read_col_unformated after write_flattened_sequence | read_col_unformated after write_nested_sequence | read_formatted_as_numpy after write_array2d | read_formatted_as_numpy after write_flattened_sequence | read_formatted_as_numpy after write_nested_sequence | read_unformated after write_array2d | read_unformated after write_flattened_sequence | read_unformated after write_nested_sequence | write_array2d | write_flattened_sequence | write_nested_sequence |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.008816 / 0.011353 (-0.002536) | 0.004691 / 0.011008 (-0.006317) | 0.100039 / 0.038508 (0.061531) | 0.035422 / 0.023109 (0.012313) | 0.312600 / 0.275898 (0.036702) | 0.378684 / 0.323480 (0.055204) | 0.007593 / 0.007986 (-0.000392) | 0.005183 / 0.004328 (0.000855) | 0.078040 / 0.004250 (0.073790) | 0.041845 / 0.037052 (0.004793) | 0.325251 / 0.258489 (0.066762) | 0.363459 / 0.293841 (0.069618) | 0.038006 / 0.128546 (-0.090540) | 0.011911 / 0.075646 (-0.063735) | 0.335020 / 0.419271 (-0.084251) | 0.048765 / 0.043533 (0.005233) | 0.305913 / 0.255139 (0.050774) | 0.337620 / 0.283200 (0.054420) | 0.101867 / 0.141683 (-0.039816) | 1.450091 / 1.452155 (-0.002064) | 1.437303 / 1.492716 (-0.055413) |

### Benchmark: benchmark_getitem\_100B.json

| metric | get_batch_of\_1024\_random_rows | get_batch_of\_1024\_rows | get_first_row | get_last_row |
|--------|---|---|---|---|
| new / old (diff) | 0.225650 / 0.018006 (0.207644) | 0.492480 / 0.000490 (0.491990) | 0.002857 / 0.000200 (0.002658) | 0.000075 / 0.000054 (0.000020) |

### Benchmark: benchmark_indices_mapping.json

| metric | select | shard | shuffle | sort | train_test_split |
|--------|---|---|---|---|---|
| new / old (diff) | 0.026231 / 0.037411 (-0.011180) | 0.105479 / 0.014526 (0.090953) | 0.118438 / 0.176557 (-0.058119) | 0.167313 / 0.737135 (-0.569822) | 0.119416 / 0.296338 (-0.176923) |

### Benchmark: benchmark_iterating.json

| metric | read 5000 | read 50000 | read_batch 50000 10 | read_batch 50000 100 | read_batch 50000 1000 | read_formatted numpy 5000 | read_formatted pandas 5000 | read_formatted tensorflow 5000 | read_formatted torch 5000 | read_formatted_batch numpy 5000 10 | read_formatted_batch numpy 5000 1000 | shuffled read 5000 | shuffled read 50000 | shuffled read_batch 50000 10 | shuffled read_batch 50000 100 | shuffled read_batch 50000 1000 | shuffled read_formatted numpy 5000 | shuffled read_formatted_batch numpy 5000 10 | shuffled read_formatted_batch numpy 5000 1000 |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.396233 / 0.215209 (0.181024) | 3.943325 / 2.077655 (1.865671) | 1.778864 / 1.504120 (0.274744) | 1.587957 / 1.541195 (0.046763) | 1.615404 / 1.468490 (0.146914) | 0.709427 / 4.584777 (-3.875350) | 3.823310 / 3.745712 (0.077598) | 3.461376 / 5.269862 (-1.808486) | 1.888330 / 4.565676 (-2.677346) | 0.086910 / 0.424275 (-0.337365) | 0.012215 / 0.007607 (0.004608) | 0.504877 / 0.226044 (0.278833) | 5.051513 / 2.268929 (2.782584) | 2.249389 / 55.444624 (-53.195235) | 1.890949 / 6.876477 (-4.985528) | 2.015584 / 2.142072 (-0.126489) | 0.862313 / 4.805227 (-3.942914) | 0.166295 / 6.500664 (-6.334369) | 0.061131 / 0.075469 (-0.014338) |

### Benchmark: benchmark_map_filter.json

| metric | filter | map fast-tokenizer batched | map identity | map identity batched | map no-op batched | map no-op batched numpy | map no-op batched pandas | map no-op batched pytorch | map no-op batched tensorflow |
|--------|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 1.201804 / 1.841788 (-0.639984) | 14.589425 / 8.074308 (6.515117) | 13.855522 / 10.191392 (3.664130) | 0.193406 / 0.680424 (-0.487018) | 0.028614 / 0.534201 (-0.505587) | 0.439857 / 0.579283 (-0.139426) | 0.443330 / 0.434364 (0.008966) | 0.514078 / 0.540337 (-0.026259) | 0.608245 / 1.386936 (-0.778691) |

</details>
PyArrow==latest

<details>
<summary>Show updated benchmarks!</summary>

### Benchmark: benchmark_array_xd.json

| metric | read_batch_formatted_as_numpy after write_array2d | read_batch_formatted_as_numpy after write_flattened_sequence | read_batch_formatted_as_numpy after write_nested_sequence | read_batch_unformated after write_array2d | read_batch_unformated after write_flattened_sequence | read_batch_unformated after write_nested_sequence | read_col_formatted_as_numpy after write_array2d | read_col_formatted_as_numpy after write_flattened_sequence | read_col_formatted_as_numpy after write_nested_sequence | read_col_unformated after write_array2d | read_col_unformated after write_flattened_sequence | read_col_unformated after write_nested_sequence | read_formatted_as_numpy after write_array2d | read_formatted_as_numpy after write_flattened_sequence | read_formatted_as_numpy after write_nested_sequence | read_unformated after write_array2d | read_unformated after write_flattened_sequence | read_unformated after write_nested_sequence | write_array2d | write_flattened_sequence | write_nested_sequence |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.007087 / 0.011353 (-0.004265) | 0.005024 / 0.011008 (-0.005985) | 0.096852 / 0.038508 (0.058344) | 0.032870 / 0.023109 (0.009761) | 0.397790 / 0.275898 (0.121892) | 0.420717 / 0.323480 (0.097237) | 0.005552 / 0.007986 (-0.002434) | 0.003742 / 0.004328 (-0.000586) | 0.074788 / 0.004250 (0.070537) | 0.048030 / 0.037052 (0.010977) | 0.398520 / 0.258489 (0.140031) | 0.460919 / 0.293841 (0.167078) | 0.037652 / 0.128546 (-0.090894) | 0.012249 / 0.075646 (-0.063397) | 0.333077 / 0.419271 (-0.086194) | 0.052364 / 0.043533 (0.008831) | 0.394358 / 0.255139 (0.139219) | 0.414193 / 0.283200 (0.130994) | 0.103569 / 0.141683 (-0.038114) | 1.499208 / 1.452155 (0.047053) | 1.619481 / 1.492716 (0.126764) |

### Benchmark: benchmark_getitem\_100B.json

| metric | get_batch_of\_1024\_random_rows | get_batch_of\_1024\_rows | get_first_row | get_last_row |
|--------|---|---|---|---|
| new / old (diff) | 0.229476 / 0.018006 (0.211470) | 0.448670 / 0.000490 (0.448180) | 0.000399 / 0.000200 (0.000199) | 0.000056 / 0.000054 (0.000001) |

### Benchmark: benchmark_indices_mapping.json

| metric | select | shard | shuffle | sort | train_test_split |
|--------|---|---|---|---|---|
| new / old (diff) | 0.027550 / 0.037411 (-0.009862) | 0.109180 / 0.014526 (0.094654) | 0.118372 / 0.176557 (-0.058185) | 0.153136 / 0.737135 (-0.583999) | 0.122689 / 0.296338 (-0.173650) |

### Benchmark: benchmark_iterating.json

| metric | read 5000 | read 50000 | read_batch 50000 10 | read_batch 50000 100 | read_batch 50000 1000 | read_formatted numpy 5000 | read_formatted pandas 5000 | read_formatted tensorflow 5000 | read_formatted torch 5000 | read_formatted_batch numpy 5000 10 | read_formatted_batch numpy 5000 1000 | shuffled read 5000 | shuffled read 50000 | shuffled read_batch 50000 10 | shuffled read_batch 50000 100 | shuffled read_batch 50000 1000 | shuffled read_formatted numpy 5000 | shuffled read_formatted_batch numpy 5000 10 | shuffled read_formatted_batch numpy 5000 1000 |
|--------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 0.445163 / 0.215209 (0.229954) | 4.426350 / 2.077655 (2.348695) | 2.194902 / 1.504120 (0.690782) | 2.019049 / 1.541195 (0.477854) | 2.032795 / 1.468490 (0.564305) | 0.700752 / 4.584777 (-3.884025) | 3.797616 / 3.745712 (0.051903) | 2.046414 / 5.269862 (-3.223447) | 1.345037 / 4.565676 (-3.220639) | 0.085389 / 0.424275 (-0.338886) | 0.012824 / 0.007607 (0.005217) | 0.553875 / 0.226044 (0.327831) | 5.550252 / 2.268929 (3.281323) | 2.702822 / 55.444624 (-52.741803) | 2.346257 / 6.876477 (-4.530220) | 2.410772 / 2.142072 (0.268699) | 0.848271 / 4.805227 (-3.956957) | 0.170787 / 6.500664 (-6.329877) | 0.064344 / 0.075469 (-0.011125) |

### Benchmark: benchmark_map_filter.json

| metric | filter | map fast-tokenizer batched | map identity | map identity batched | map no-op batched | map no-op batched numpy | map no-op batched pandas | map no-op batched pytorch | map no-op batched tensorflow |
|--------|---|---|---|---|---|---|---|---|---|
| new / old (diff) | 1.266222 / 1.841788 (-0.575566) | 14.501194 / 8.074308 (6.426886) | 13.413678 / 10.191392 (3.222286) | 0.589048 / 0.680424 (-0.091375) | 0.018246 / 0.534201 (-0.515955) | 0.425221 / 0.579283 (-0.154062) | 0.425900 / 0.434364 (-0.008464) | 0.494023 / 0.540337 (-0.046314) | 0.604324 / 1.386936 (-0.782612) |

</details>
</details>

![](https://cml.dev/watermark.png "CML watermark")