Hello! I have about a code that needs blocking:

self.search_params['my_sex'] = '' self.search_params['wish_sex'] = 'F' with (yield self.application.search_lock.acquire()): for uid in self.application.inSearch: if isComplyUsers(self.search_params, self.application.pool[uid]): self.connected(self.uid, uid) self.application.inSearch.pop(uid) return True self.application.inSearch.append(self.uid) 

The function itself isComplyUsers:

  def isComplyUsers(user, user1): if(user['my_sex']!='' and user['wish_sex']!='' and user['wish_sex']!=user1['my_sex']): return False return True 

self.application.search_lock - tornado.locks.Lock ()

Of course, I reduced the code, separating only the main points because of what the error occurs.
Sometimes an error pops up in the log:

 __del__ future <tornado.object.concurrent.Future object exception 

And he complains about KeyError, and says that 'my_sex' does not exist in the user object. So one wonders why he calls this function at all in his destructor "__del__". And if I just check for the emptiness of the object - will this be a solution? Also, I noticed that the error appears only if search_params ['my_sex'] = '' is exactly equal to emptiness, if it is not equal to something empty, then an error does not occur.

  • From the above code it is not at all clear what the blocking is used for. And the phrase "there is a cycle in the blocking itself coming from users" does not add clarity. Give more code. - Nikmoon
  • But I am interested in the mechanism of work of locks and why it happens as I described. Having added the code I’ll just make a mess of people - iproger
  • I added the code so that you could understand why the lock was so that one person could not connect with two. but where is this - it is not clear. - iproger
  • First, the lock should be used in cororne. Second, how is blocking released? - Nikmoon
  • the same statement with, it is released immediately after the execution of the action. And what does "blocking should be used in corintine"? - iproger

2 answers 2

If you understand how asynchrony works in tornado , then the principle of operation of tornado.locks.Lock easy to explain with an example.

Suppose we have a list that we want to protect from reading during editing, and from editing during reading.

 from tornado import gen, locks myList = [] listLock = locks.Lock() @gen.coroutine def read_list(): with (yield listLock.acqire()): for rec in myList: # ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠΉ записи # ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ асинхронныС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ, # Ρ‚.ΠΊ. Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ списка всС Ρ€Π°Π²Π½ΠΎ Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΎ pass @gen.coroutine def write_to_list(): with (yield listLock.acqire()): # ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠ°ΠΊ ΡƒΠ³ΠΎΠ΄Π½ΠΎ Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ список, # Π² Ρ‚ΠΎΠΌ числС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π»ΡŽΠ±Ρ‹Π΅ асинхронныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Ρ‚.ΠΊ. # Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ списка Π·Π°Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²Π°Π½ΠΎ pass 

If in the described functions do not use asynchronous operations, the lock is not needed, because tornado runs in one thread.

  • Thanks, added "@ gen.coroutine". But the error remained. And the tornado does not work in the same stream. If that were the case, then with 2,000 thousand simultaneous requests everything would hang, but he quickly dealt with them quickly and at the same time other requests are also executed without a hang. But this is all absolutely not important, it is the lock error, and I know for sure that I need it. Because while there was no blocking there were errors such that a person connected with someone, plus someone connected with him, that is, at the same time a search occurred. I am interested in the mechanism of their work inside, why the function is called during the destructor - iproger
  • Enlighten about the Tornado . Tornado uses a single-threaded event loop. - Nikmoon
  • Yes, only I use tornado.ioloop.IOLoop - iproger

After looking at the tornado code, an error did not occur in the destructor!) Just for some reason, gen.coroutine collects all the errors and only when the object is destroyed returns all the errors that were. It is strange that here I was no one suggested. After that, I immediately began to look for an error, why there may be empty objects in the search and found an error!)
Nikmoon , you were right, but I would immediately be told that the destructor returns the saved errors, only then I would understand where to look for the error, thanks!)

  • To be honest, I didn’t know that either, we take into account) - Nikmoon