简体   繁体   中英

Shelve gives AttributeError in Python 3.3 for hello world example using the “with shelve.open” syntax, but not without it

I'm trying to use shelve with Python 3.3. It is recommended to use the with shelve.open('spam.db') as db:... syntax to ensure we close the "connection". However, when I try it I get the following error AttributeError: __exit__ . What gives? Any thoughts? Many similar questions here, although couldn't find a satisfying solution. The following shows what I have attempted thus far:

The following fails:

import shelve
with shelve.open('spam.db') as db:
    db['key'] = 'value'
    print(db['key'])

Error message:

Traceback (most recent call last):
  File "D:\arbitrary_path_to_script\nf_shelve_test.py", line 3, in <module>
    with shelve.open('spam.db') as db:
AttributeError: __exit__
[Finished in 0.1s with exit code 1]

The following works:

import shelve
db = shelve.open('spam.db')
db['key'] = 'value'
print(db['key'])
db.close()

And outputs the expected:

value
[Finished in 0.1s]

Printing the shelve module path

import shelve
print(shelve)

Location:

<module 'shelve' from 'C:\\Python33\\lib\\shelve.py'>
[Finished in 0.1s]

In Python 3.3 shelve.open() is not a context manager and cannot be used in a with statement. The with statement expects there to be __enter__ and __exit__ methods ; the error you see is because there are no such methods.

You can use contextlib.closing() to wrap the shelve.open() result in a context manager here:

from contextlib import closing

with closing(shelve.open('spam.db')) as db:

Alternatively, upgrade to Python 3.4, where the required context manager methods were added to the return value of shelve.open() . From the shelve.Shelve documentation :

Changed in version 3.4 : Added context manager support.

Shelf isn't a context manager in Python 3.3; this functionality was introduced in 3.4. If you need to support 3.3, you'll need to use contextlib.closing or an explicit close in a finally block. I recommend contextlib.closing .

import contextlib

with contextlib.closing(shelve.open('spam.db')) as db:
    do_whatever_with(db)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM