openpaperwork / pyinsane

Python library to access and use image scanners (Linux/Windows/etc) (Sane/WIA) -- Moved to Gnome's Gitlab
https://gitlab.gnome.org/World/OpenPaperwork/pyinsane
63 stars 24 forks source link

Using abstract_th module does not allow more than three executions #16

Closed trashgordon-zz closed 10 years ago

trashgordon-zz commented 10 years ago

I wasn't sure if I should submit this as an issue because I don't know if this a problem with my code or the pyinsane library. I'm building a Qt (PySide) GUI application and utilizing threading through the QThread class. I am using the pyinsane.abstract_th module for scanning.

I am able to execute a scan successfully when pushing a button on my application. After the scan completes, I can execute another scan. The problem is the third attempt at execution, which hangs indefinitely. It hangs when attempting to set options for the scan. Here is the snippet of code where the hanging occurs:

def _get_scanner():
    print('Inside _get_scanner()')
    scanner_name = 'epkowa:net:192.168.1.8'
    return pyinsane.Scanner(name=scanner_name)

def scan(mode=None,res=None,source=None,filename=None):
    print('Inside scan()')
    scanner = _get_scanner()

    #For Testing
    devices = pyinsane.get_devices()
    if (len(devices) <= 0):
        print('No scanner detected!')
        sys.exit(1)
    print('Devices detected:')
    print('- ' + '\n- '.join([str(d) for d in devices]))

    print('Setting scan options...')
    # HANGS AFTER PRINTING THE ABOVE LINE
    try:
        scanner.options['resolution'].value = res
    except (KeyError, pyinsane.SaneException) as exc:
        print('Failed to set %s to %s: %s' % ('resolution', str(res), str(exc)))

I noticed that when I retrieve the available devices, my network scanner (epkowa:net:192.168.1.8) is found the first execution, but then is not in subsequent executions (button pushes). However, even though it is not found in the second attempt, the scan still completes successfully.

I have also tried this with the pyinsane.abstract module, which will execute one scan just fine. However, on additional attempts I get the following error after executing scanner.scan(multiple=False):

Traceback (most recent call last):
  File "main.py", line 90, in process
    docscan.scan(self.mode, self.res, self.source, self.filename)
  File "/home/dev/python_projects/scanimage_gui/docscan.py", line 38, in scan
    scan_session = scanner.scan(multiple=False)
  File "/home/dev/python_projects/scanimage_gui/pyinsane/abstract.py", line 455, in scan
    scan = SingleScan(self)
  File "/home/dev/python_projects/scanimage_gui/pyinsane/abstract.py", line 273, in __init__
    self._init()
  File "/home/dev/python_projects/scanimage_gui/pyinsane/abstract.py", line 175, in _init
    rawapi.sane_start(sane_dev_handle[1])
  File "/home/dev/python_projects/scanimage_gui/pyinsane/rawapi.py", line 674, in sane_start
    raise SaneException(SaneStatus(status))
pyinsane.rawapi.SaneException: <class 'pyinsane.rawapi.SaneStatus'> : Error during device I/O (9)

I have tried deleting the Qt worker and thread objects in my PySide application after the scan completes to make sure the thread has released its handle on the scanner, but that doesn't seem to make a difference.

Again, I'm not sure where the issue lies, but I thought I would at least throw this out to narrow down the problem. By the way, everything works correctly when not using threading. I can execute as many scan operations as I want. I want to use threading, though, due to GUI blocking issues in my Qt app.

Please let me know if you would like additional code to review.

Thanks!

jflesch commented 10 years ago

Hello,

First, let's get rid of the usual suspects : does it happen with other applications ? For instance, with simple-scan, can you do more 3 scans or more ?

trashgordon-zz commented 10 years ago

Thank you for the quick reply. When you say simple-scan, do you mean this (https://launchpad.net/simple-scan) or the code on your github page that does a simple scan? If you mean the application on launchpad.net, is that multi-threaded? I am able to do more than 2 scans by using just the pyinsane.abstract module. I am also able to do more than 2 scans with "Image Scan! for Linux".

jflesch commented 10 years ago

I was thinking about the application 'simple-scan' ( https://launchpad.net/simple-scan ). The point was just to make sure it's not simply the Sane driver that you're using which is faulty. But I guess what you just told me answer the question as well.

Another test you could do is try with Paperwork. It uses pyinsane.abstract_th. It could give us a hint about whether the problem comes from Pyinsane or your program.

trashgordon-zz commented 10 years ago

I just tested with Paperwork, and it does a single scan. However, (maybe I should file this under your Paperwork issues) my scanner does not show up the second time under the device list. It showed the first time, but not the second. I was also seeing this issue with my app as well. Maybe this is causing a problem? I wonder why my scanner wouldn't be "found" on additional scans?

trashgordon-zz commented 10 years ago

I was able to get this fixed. Based on the error message when trying to use the pyinsane.abstract module, I had a hunch that my program was trying to obtain multiple handles to the scanner. So I moved the scanner object I was creating to my main class's constructor rather than creating a new scanner object each time I wanted to run a scan. This way, only one handle was obtained throughout the lifetime of the program. This allows me to still use threads in my program, but because the scanner object is only created once, I can perform multiple scans.

Thank you for digging into this for me. This issue can be closed.

Thanks!

jflesch commented 10 years ago

Hm, it feels like it should work. Even if it's related to a Sane limitation, Pyinsane should work around it. I'll try to keep that problem in mind for later.

trashgordon-zz commented 10 years ago

OK, thanks. I should've mentioned, too, that I was able to get this working in both the abstract and abstract_th modules.