[Tutor] program hangs in while loop using wx.yield

Alex Hall mehgcap at gmail.com
Sun Nov 14 19:35:09 CET 2010


On 11/14/10, Alan Gauld <alan.gauld at btinternet.com> wrote:
> "Alex Hall" <mehgcap at gmail.com> wrote
>
>> I had this working back in the summer, but have since had to
>> restructure some things in the code. Now, my program is hanging
>> while
>> it waits for the human player to take his/her turn, and I am not
>> sure
>> how to free it;
>
> I don't really understand this concept in a GUI?
> Why would you be waitying for the user?
> Surely you should just go back to the mainloop
> and let the GUI control the users input? Then
> after processing that call the computer move code.
> Something like:
>
> def handle_user_move_event():
>      processMoveOnGUI()
>      movedata = generateComputerMove()
>      processMoveOnGUI()
>      return
>
> Thats what I would expect to see.
The problem is that I want to go until there is a winner. You are
right about just letting the mainloop of the gui handle input (I
forgot the gui is already looping and waiting for input) but I would
like to make the user pause while the computer goes, this way the user
cannot just keep hammering out moves as fast as possible and input can
be given to the user properly. Therefore, I have gotten rid of the
loop I sent originally, but I still have a loop which switches between
the two players as well as passing the results of one player's move to
the other. If I fire (it is Battleship) and hit your ship,and I am the
computer, then this loop will give you the information about where I
fired. You will check to see if it was a hit and, since it was, pass
back information about what was hit. You will also update the gui to
reflect the new status of the damaged ship. However, while I am doing
this, I do not want you firing as fast as possible, and I want you to
take in the results before you are allowed to fire.
I realize it is all rather confusing without seeing the code, but the
loop itself is somewhat complex unless you can see what all the
functions are doing. Still, here is the new loop:

 while not player1.isWinner or not player2.isWinner:
  if player1.grid.turnOver:
   print("player2 is going")
   player1.grid.speak("player 2 is going.")
   player2.enemyMove=player1.grid.cmd #tell p2 what p1 just did
   player1.lock() #so p1 cannot interact with the gui
   player2.takeTurn() #decides what to do and updates its Grid object
accordingly
   player1.grid.speak(helpers.interpret(player2.grid.cmd)) #just
output what p2 did after takeTurn() is over
  elif player2.grid.turnOver:
   print("player1 is going")
   player1.enemyMove=player2.grid.cmd
   player1.unlock() #p1 can now interact with the gui
   player1.grid.speak("It is now your turn.")
   player1.takeTurn()
  #end if
  #wx.Yield()
  time.sleep(.1)
 #end while

>
>>  while not self.grid.turnOver:
>>   print("in while") #just a test to make sure I got this far
>>   wx.Yield()
>>   time.sleep(1)
>>  #end while
>
> So this is presumably buried in some very long and complex method
> that you have written and you are briefly giving control back to
> wxPython
> before continuing your processing? Except that you appear to just
> cycle continually giving back control? It doesn't seem to make sense.
I am honestly not sure how all the control flows, but this loop is
gone so hopefully it will not be a problem.
>
>> some of them change the Grid's "turnOver" variable. Therefore, I
>> loop
>> until I see that the user performed an action on the grid that sets
>> the Grid's turnOver to true, at which point the loop stops and the
>> other user (a computer in this case) can go.
>
> Why are you doing all this inside ane event handler? Why don't
> you just make your move and hand back to the GUI?
>
>
>> The problem is that this loop makes the app hang,
>> with Windows saying it is not responding. Of
>> course, the user can now not do anything at all, so I have to use
>> ctrl-c from the cmd window where I launched it to kill it.
>
> No idea why its doing that. Have you tried playing with the
> Yield parameter and return value to see if they give a clue?
>
> But frankly I'd look to reconstruct the code to avoid the use
> of Yield completely. Yield should almost be a last resort...
>
>> time to call any Grid function. Is this solvable, or should I just
>> use
>> threads?
>
>
> Based on the loop you posted you shouldn't need threads,
> just exit your method and wait for the user to do something
> and catch that event to restart your code. Leave it to the GUI.
>
> HTH,
>
> --
> Alan Gauld
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/
>
>
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
>


-- 
Have a great day,
Alex (msg sent from GMail website)
mehgcap at gmail.com; http://www.facebook.com/mehgcap


More information about the Tutor mailing list