def rcvdata(cmd,size): global s; s.settimeout(1) try: sendCommand(cmd);data = s.recv(size) except: try: sendCommand(cmd);data = s.recv(size) except: try: sendCommand(cmd);data = s.recv(size) except: try: sendCommand(cmd);data = s.recv(size) except: try: sendCommand(cmd);data = s.recv(size) except: try: sendCommand(cmd);data = s.recv(size) except: s.close() return(data) 
  • while for N times? - user207618
  • If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky

3 answers 3

 def rcvdata(cmd, size): data = None s.settimeout(1) for trying in range(6): try: sendCommand(cmd) data = s.recv(size) except: if trying == 5: # Последняя попытка, неудачная s.close() return data 

Or if there is no need for any actions after the cycle, then nesting can be reduced:

 def rcvdata(cmd, size): s.settimeout(1) for _ in range(6): try: sendCommand(cmd) return s.recv(size) except: pass # Здесь по желанию можно воткнуть time.sleep(1) # Сюда мы попадаем только после шести неудачных попыток s.close() return None 

Check out any Python tutorial about loops.


It is also not good to intercept ALL exceptions, because then the program cannot be closed (the output is also quite a SystemExit exception and sometimes a KeyboardInterrupt), and bugs inside the sendCommand will also be skipped. You should catch only those exceptions that are expected here (here, probably, something like socket.error or IOError ).

And s.recv(size) does not guarantee that exactly size bytes will come - depending on the quality of communication, OS features, phase of the moon and stars in the sky may return less. And on timeout - and just zero bytes at all. I do not know if this is necessary in your particular case, but it is advisable not to forget about it.

In general, code is not good anyway

  • Do not use except:pass to allow KeyboardInterrupt , SystemExit replace with except Exception and / or to find bugs, for example, leading to AttributeError , you can logging.exception("error") . The text you said about it, but the code uses except:pass - jfs
  • @jfs I do not dare to change the logic of the code taken out of context. If the author specifies that what he needs - I will change - andreymal
  • Given the state of the code in the question - "I dare not change the logic" is an excuse. We are not on the author's help site, your answer should help other visitors, and not in the expectation that the author has an extremely rare case when the construction is harmful in all other cases is justified. - jfs
  • That's exactly considering the state in the code in question, I do not dare to change the logic. :) Other visitors will completely read my note and your first comment. Moreover, the question is not about intercepting exceptions. - andreymal
  • considering the status of the code, the likelihood of bugs in the code inside except:pass is close to 100% — it's more important to avoid such code here. - jfs

I will offer my version with a delay between calling recv in 1 second and 10 attempts:

 def rcvdata(cmd, size): global s s.settimeout(1) max_count = 10 while True: try: max_count -= 1 if max_count <= 0: return sendCommand(cmd) data = s.recv(size) return data finally: s.close() 
  • Taking into account that we do not know where the code in the question is from and where it is used and what is happening with s outside the function, such argues may not be entirely correct - andreymal
  • By the way, there is a delay in one second even after a successful attempt - andreymal
  • I agree, just showing an example) I was not sure of the delay, thanks for the clarification :) - gil9red

I'll leave my option_)

 def rcvdata(cmd,size): global s; s.settimeout(1) t = 0 while t!=7: try: sendCommand(cmd) data = s.recv(size) except: t+=1 s.close()