jeffbass / imagezmq

A set of Python classes that transport OpenCV images from one computer to another using PyZMQ messaging.
MIT License
1.01k stars 160 forks source link

'ImageSender' object has no attribute 'close' #39

Closed yigitcan closed 4 years ago

yigitcan commented 4 years ago

I am getting this exception thrown when I try to close the stream from an ImageSender instance.

'ImageSender' object has no attribute 'close'

Thanks for your help!

yigitcan commented 4 years ago

Realised I was running version 1.0.1 and updated to 1.1.1 (latest)

Now I get a different exception for the same operation: Socket operation on non-socket

jeffbass commented 4 years ago

Both errors (the one you experienced in v1.0.1 and the new one in v1.1.1) are related to ZMQ not actually activating a socket correctly. By design, imageZMQ has no error checking; it relies on ZMQ error trapping instead. Are you sure a socket was successfully created? If so, can you share some code snippets? And share which OS and Python versions you are using? Errors like this are, in my own experience, due to bad tcp address or bad socket number or mis-matched address or socket or both between sender and receiver. Any of those can cause socket errors. My first guess is that the socket did not startup successfully.

yigitcan commented 4 years ago

Hi Jeff,

In my case, I have both client and server in the same codebase. I have several camera objects that continuously send frames in their own separate threads. When one of these cameras is deleted, I want to be able to stop ImageSender to send frames in the background for that camera.

#method is running in a separate thread
def _start_streaming(self, cam_id):

        if cam_id not in self.cameras:
            return

        camera = self.cameras[cam_id]

        try:
            sender = ImageSender(
                connect_to="tcp://*:{}".format(camera.stream_port), REQ_REP=False)

            vs = VideoStream(src=camera.ip_address).start()

            while True:
                if (cam_id not in self.cameras):
                    break

                frame = vs.read()
                if frame is None:
                    break

                sender.send_image(camera.cam_id, frame)
                time.sleep(0.1)

            vs.stop()
            sender.close()
            self.remove_camera(cam_id)

        except Exception as e:
            print("Exception cam {} : {}".format(cam_id, e))
            return
jeffbass commented 4 years ago

I have 2 thoughts when I see your code above: 1) change tcp address to a specific one rather than "*": try using "tcp://127.0.0.1:{}" instead. This may be important, especially with multiple cameras as publishers, and 2) one sender.close may be closing the socket of a different ImageSender sender depending on how your threads are started and progressing. I see that camera is an instance property (camera = self.cameras(cam_id)). Perhaps make the variable sender an instance property as well? Try changing sender to self.sender in each use. Perhaps try 1) and if that doesn't fix it, try 2) and let's go from there. Thanks for your help in debugging this. Jeff

yigitcan commented 4 years ago

Thanks Jeff. I have solved this issue by creating a global reference to all open threads, and sending a signal to the specific thread when I need their stream to stop. It was in the end not related to the Imagezmq. I will close the issue.

Just wanted to take the opportunity to thank you for building this very useful module, and being very responsive! 🙏