Search code examples
pythonimagepython-2.7python-imaging-librarybuffering

AttributeError: __exit__ while buffering downloaded image on python 2.7


I'm trying to automate captcha file recognition with a python script. However, after several days of efforts my functions seems to be far from desired result.

Furthermore, the traceback I've got is not informative enough to help me investigate further.

Here is my function:

def getmsg():
    solved = ''
    probe_request = []
    try:
        probe_request = api.messages.get(offset = 0, count = 2)
    except apierror, e:
        if e.code is 14:
            key = e.captcha_sid
            imagefile = cStringIO.StringIO(urllib.urlopen(e.captcha_img).read())
            img = Image.open(imagefile)
            imagebuf = img.load()
            with imagebuf as captcha_file:
                captcha = cptapi.solve(captcha_file)
    finally:
        while solved is None:
            solved = captcha.try_get_result()
            tm.sleep(1.500)
        print probe_request

Here is the traceback:

Traceback (most recent call last):
  File "myscript.py", line 158, in <module>
    getmsg()
  File "myscript.py", line 147, in getmsg
    with imagebuf as captcha_file:
AttributeError: __exit__

Can someone please clarify what exactly I'm doing wrong?

Also I did not succeed with image processing without buffering:

key = e.captcha_sid
response = requests.get(e.captcha_img)
img = Image.open(StringIO.StringIO(response.content))
with img as captcha_file:
    captcha = cptapi.solve(captcha_file)

Which leads to:

    captcha = cptapi.solve(captcha_file)
  File "/usr/local/lib/python2.7/dist-packages/twocaptchaapi/__init__.py", line 62, in proxy
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/twocaptchaapi/__init__.py", line 75, in proxy
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/twocaptchaapi/__init__.py", line 147, in solve
    raw_data = file.read()
  File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 632, in __getattr__
    raise AttributeError(name)
AttributeError: read

Solution

  • imagebuf is not a context manager. You can't use it in a with statement, which tests for a context manager by first storing the contextmanager.__exit__ method. There is no need to close it either.

    cptapi.solve requires a file-like object; from the solve() docstring:

    Queues a captcha for solving. file may either be a path or a file object.

    There is no point in passing in an Image object here, just pass in the StringIO instance instead:

    imagefile = cStringIO.StringIO(urllib.urlopen(e.captcha_img).read())
    captcha = cptapi.solve(imagefile)
    

    Again, there is no need to use close that object here, you don't need to use with.