State Clearing in Python Turtle












0















I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator is invoked and the traceback points to what I think is the aTurtle variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?



This was constructed and executed in Jupyter and tested in qtconsole as well. Code is listed below:



import turtle
aTurtle = turtle.Turtle()

#Functions
def drawLS(aTurtle, instructions):
for cmd in instructions:
if cmd == 'F':
aTurtle.forward(5)
elif cmd == '+':
aTurtle.right(70)
elif cmd == '-':
aTurtle.left(70)
else :
print('Error : %s is an unknown command '%cmd)

def applyProduction():
axiom = 'F'
myRules = {'F': 'F-F++F-F'}
for i in range(n):
newString = ""
for ch in axiom :
newString = newString + myRules.get(ch, ch)
axiom = newString
return axiom

def lsystem():
win = turtle.Screen()
aTurtle.up()
aTurtle.setposition(-200, 0)
aTurtle.down()
aTurtle.setheading(0)
newRules = applyProduction()
drawLS (aTurtle, newRules)
win.exitonclick()

#Main
while True:
try:
n = int(input("Enter an integer greater than 0: "))
break
except:
print ("Error, input was not an integer, please try again.")
if n < 1:
print ("Error, input was not an integer greater than 0.")
else:
lsystem()









share|improve this question





























    0















    I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator is invoked and the traceback points to what I think is the aTurtle variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?



    This was constructed and executed in Jupyter and tested in qtconsole as well. Code is listed below:



    import turtle
    aTurtle = turtle.Turtle()

    #Functions
    def drawLS(aTurtle, instructions):
    for cmd in instructions:
    if cmd == 'F':
    aTurtle.forward(5)
    elif cmd == '+':
    aTurtle.right(70)
    elif cmd == '-':
    aTurtle.left(70)
    else :
    print('Error : %s is an unknown command '%cmd)

    def applyProduction():
    axiom = 'F'
    myRules = {'F': 'F-F++F-F'}
    for i in range(n):
    newString = ""
    for ch in axiom :
    newString = newString + myRules.get(ch, ch)
    axiom = newString
    return axiom

    def lsystem():
    win = turtle.Screen()
    aTurtle.up()
    aTurtle.setposition(-200, 0)
    aTurtle.down()
    aTurtle.setheading(0)
    newRules = applyProduction()
    drawLS (aTurtle, newRules)
    win.exitonclick()

    #Main
    while True:
    try:
    n = int(input("Enter an integer greater than 0: "))
    break
    except:
    print ("Error, input was not an integer, please try again.")
    if n < 1:
    print ("Error, input was not an integer greater than 0.")
    else:
    lsystem()









    share|improve this question



























      0












      0








      0








      I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator is invoked and the traceback points to what I think is the aTurtle variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?



      This was constructed and executed in Jupyter and tested in qtconsole as well. Code is listed below:



      import turtle
      aTurtle = turtle.Turtle()

      #Functions
      def drawLS(aTurtle, instructions):
      for cmd in instructions:
      if cmd == 'F':
      aTurtle.forward(5)
      elif cmd == '+':
      aTurtle.right(70)
      elif cmd == '-':
      aTurtle.left(70)
      else :
      print('Error : %s is an unknown command '%cmd)

      def applyProduction():
      axiom = 'F'
      myRules = {'F': 'F-F++F-F'}
      for i in range(n):
      newString = ""
      for ch in axiom :
      newString = newString + myRules.get(ch, ch)
      axiom = newString
      return axiom

      def lsystem():
      win = turtle.Screen()
      aTurtle.up()
      aTurtle.setposition(-200, 0)
      aTurtle.down()
      aTurtle.setheading(0)
      newRules = applyProduction()
      drawLS (aTurtle, newRules)
      win.exitonclick()

      #Main
      while True:
      try:
      n = int(input("Enter an integer greater than 0: "))
      break
      except:
      print ("Error, input was not an integer, please try again.")
      if n < 1:
      print ("Error, input was not an integer greater than 0.")
      else:
      lsystem()









      share|improve this question
















      I'm writing a program that asks a user for an integer > 0 which is used as the complexity factor for drawing a Koch curve. The program executes fine, once. When running a second time the Terminator is invoked and the traceback points to what I think is the aTurtle variable not clearing it's last state. If I restart the kernel, and clear all outputs, it works fine again once, then the issue repeats. What am I overlooking?



      This was constructed and executed in Jupyter and tested in qtconsole as well. Code is listed below:



      import turtle
      aTurtle = turtle.Turtle()

      #Functions
      def drawLS(aTurtle, instructions):
      for cmd in instructions:
      if cmd == 'F':
      aTurtle.forward(5)
      elif cmd == '+':
      aTurtle.right(70)
      elif cmd == '-':
      aTurtle.left(70)
      else :
      print('Error : %s is an unknown command '%cmd)

      def applyProduction():
      axiom = 'F'
      myRules = {'F': 'F-F++F-F'}
      for i in range(n):
      newString = ""
      for ch in axiom :
      newString = newString + myRules.get(ch, ch)
      axiom = newString
      return axiom

      def lsystem():
      win = turtle.Screen()
      aTurtle.up()
      aTurtle.setposition(-200, 0)
      aTurtle.down()
      aTurtle.setheading(0)
      newRules = applyProduction()
      drawLS (aTurtle, newRules)
      win.exitonclick()

      #Main
      while True:
      try:
      n = int(input("Enter an integer greater than 0: "))
      break
      except:
      print ("Error, input was not an integer, please try again.")
      if n < 1:
      print ("Error, input was not an integer greater than 0.")
      else:
      lsystem()






      python turtle-graphics






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 28 '18 at 21:49









      cdlane

      19.7k21245




      19.7k21245










      asked Nov 28 '18 at 19:58









      P-SidesP-Sides

      127




      127
























          1 Answer
          1






          active

          oldest

          votes


















          0














          Generally, you shouldn't plan to survive a win.exitonclick() or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear() or possibly win.reset(). I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick(), and to use the graphic numinput():



          from turtle import Screen, Turtle

          def drawLS(turtle, instructions):
          for cmd in instructions:
          if cmd == 'F':
          turtle.forward(5)
          elif cmd == '+':
          turtle.right(70)
          elif cmd == '-':
          turtle.left(70)
          else:
          print('Error : %s is an unknown command '%cmd)

          def applyProduction(n):
          axiom = 'F'
          myRules = {'F': 'F-F++F-F'}

          for _ in range(n):
          newString = ""
          for ch in axiom:
          newString += myRules.get(ch, ch)
          axiom = newString

          return axiom

          def lsystem(n):
          aTurtle.up()
          aTurtle.setposition(-200, 0)
          aTurtle.down()
          aTurtle.setheading(0)
          newRules = applyProduction(n)
          drawLS(aTurtle, newRules)

          def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
          screen.onclick(None)

          n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)

          if n is not None:
          screen.clear()
          lsystem(int(n))

          screen.onclick(prompt)

          screen = Screen()

          aTurtle = Turtle()
          aTurtle.speed('fastest') # because I have no patience

          prompt()

          screen.mainloop()


          When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.






          share|improve this answer
























          • Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

            – P-Sides
            Nov 29 '18 at 22:25











          • @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

            – cdlane
            Nov 29 '18 at 23:56











          • Ok thank you, this satisfies the original intent of the small program.

            – P-Sides
            Nov 30 '18 at 17:37












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53527194%2fstate-clearing-in-python-turtle%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          Generally, you shouldn't plan to survive a win.exitonclick() or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear() or possibly win.reset(). I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick(), and to use the graphic numinput():



          from turtle import Screen, Turtle

          def drawLS(turtle, instructions):
          for cmd in instructions:
          if cmd == 'F':
          turtle.forward(5)
          elif cmd == '+':
          turtle.right(70)
          elif cmd == '-':
          turtle.left(70)
          else:
          print('Error : %s is an unknown command '%cmd)

          def applyProduction(n):
          axiom = 'F'
          myRules = {'F': 'F-F++F-F'}

          for _ in range(n):
          newString = ""
          for ch in axiom:
          newString += myRules.get(ch, ch)
          axiom = newString

          return axiom

          def lsystem(n):
          aTurtle.up()
          aTurtle.setposition(-200, 0)
          aTurtle.down()
          aTurtle.setheading(0)
          newRules = applyProduction(n)
          drawLS(aTurtle, newRules)

          def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
          screen.onclick(None)

          n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)

          if n is not None:
          screen.clear()
          lsystem(int(n))

          screen.onclick(prompt)

          screen = Screen()

          aTurtle = Turtle()
          aTurtle.speed('fastest') # because I have no patience

          prompt()

          screen.mainloop()


          When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.






          share|improve this answer
























          • Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

            – P-Sides
            Nov 29 '18 at 22:25











          • @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

            – cdlane
            Nov 29 '18 at 23:56











          • Ok thank you, this satisfies the original intent of the small program.

            – P-Sides
            Nov 30 '18 at 17:37
















          0














          Generally, you shouldn't plan to survive a win.exitonclick() or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear() or possibly win.reset(). I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick(), and to use the graphic numinput():



          from turtle import Screen, Turtle

          def drawLS(turtle, instructions):
          for cmd in instructions:
          if cmd == 'F':
          turtle.forward(5)
          elif cmd == '+':
          turtle.right(70)
          elif cmd == '-':
          turtle.left(70)
          else:
          print('Error : %s is an unknown command '%cmd)

          def applyProduction(n):
          axiom = 'F'
          myRules = {'F': 'F-F++F-F'}

          for _ in range(n):
          newString = ""
          for ch in axiom:
          newString += myRules.get(ch, ch)
          axiom = newString

          return axiom

          def lsystem(n):
          aTurtle.up()
          aTurtle.setposition(-200, 0)
          aTurtle.down()
          aTurtle.setheading(0)
          newRules = applyProduction(n)
          drawLS(aTurtle, newRules)

          def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
          screen.onclick(None)

          n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)

          if n is not None:
          screen.clear()
          lsystem(int(n))

          screen.onclick(prompt)

          screen = Screen()

          aTurtle = Turtle()
          aTurtle.speed('fastest') # because I have no patience

          prompt()

          screen.mainloop()


          When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.






          share|improve this answer
























          • Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

            – P-Sides
            Nov 29 '18 at 22:25











          • @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

            – cdlane
            Nov 29 '18 at 23:56











          • Ok thank you, this satisfies the original intent of the small program.

            – P-Sides
            Nov 30 '18 at 17:37














          0












          0








          0







          Generally, you shouldn't plan to survive a win.exitonclick() or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear() or possibly win.reset(). I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick(), and to use the graphic numinput():



          from turtle import Screen, Turtle

          def drawLS(turtle, instructions):
          for cmd in instructions:
          if cmd == 'F':
          turtle.forward(5)
          elif cmd == '+':
          turtle.right(70)
          elif cmd == '-':
          turtle.left(70)
          else:
          print('Error : %s is an unknown command '%cmd)

          def applyProduction(n):
          axiom = 'F'
          myRules = {'F': 'F-F++F-F'}

          for _ in range(n):
          newString = ""
          for ch in axiom:
          newString += myRules.get(ch, ch)
          axiom = newString

          return axiom

          def lsystem(n):
          aTurtle.up()
          aTurtle.setposition(-200, 0)
          aTurtle.down()
          aTurtle.setheading(0)
          newRules = applyProduction(n)
          drawLS(aTurtle, newRules)

          def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
          screen.onclick(None)

          n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)

          if n is not None:
          screen.clear()
          lsystem(int(n))

          screen.onclick(prompt)

          screen = Screen()

          aTurtle = Turtle()
          aTurtle.speed('fastest') # because I have no patience

          prompt()

          screen.mainloop()


          When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.






          share|improve this answer













          Generally, you shouldn't plan to survive a win.exitonclick() or any of the other turtle commands that turn control over to the tkinter event loop. There are tricks for doing so but not worth the trouble when it's easier just to avoid this situation. What you want is win.clear() or possibly win.reset(). I've incorporated that below and rewrote your prompting logic to use it's own click event, instead of exitonclick(), and to use the graphic numinput():



          from turtle import Screen, Turtle

          def drawLS(turtle, instructions):
          for cmd in instructions:
          if cmd == 'F':
          turtle.forward(5)
          elif cmd == '+':
          turtle.right(70)
          elif cmd == '-':
          turtle.left(70)
          else:
          print('Error : %s is an unknown command '%cmd)

          def applyProduction(n):
          axiom = 'F'
          myRules = {'F': 'F-F++F-F'}

          for _ in range(n):
          newString = ""
          for ch in axiom:
          newString += myRules.get(ch, ch)
          axiom = newString

          return axiom

          def lsystem(n):
          aTurtle.up()
          aTurtle.setposition(-200, 0)
          aTurtle.down()
          aTurtle.setheading(0)
          newRules = applyProduction(n)
          drawLS(aTurtle, newRules)

          def prompt(x=None, y=None): # dummy arguments for onclick(), ignore them
          screen.onclick(None)

          n = screen.numinput("Complexity Factor", "Enter an integer greater than 0", minval=1, maxval=100)

          if n is not None:
          screen.clear()
          lsystem(int(n))

          screen.onclick(prompt)

          screen = Screen()

          aTurtle = Turtle()
          aTurtle.speed('fastest') # because I have no patience

          prompt()

          screen.mainloop()


          When the drawing finishes, click on the screen to get a new prompt for a different complexity factor and a new drawing.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 28 '18 at 21:40









          cdlanecdlane

          19.7k21245




          19.7k21245













          • Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

            – P-Sides
            Nov 29 '18 at 22:25











          • @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

            – cdlane
            Nov 29 '18 at 23:56











          • Ok thank you, this satisfies the original intent of the small program.

            – P-Sides
            Nov 30 '18 at 17:37



















          • Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

            – P-Sides
            Nov 29 '18 at 22:25











          • @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

            – cdlane
            Nov 29 '18 at 23:56











          • Ok thank you, this satisfies the original intent of the small program.

            – P-Sides
            Nov 30 '18 at 17:37

















          Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

          – P-Sides
          Nov 29 '18 at 22:25





          Ok, so I see the code purely ignores n if it is a positive non-integer but allows you to click the screen again. Would I be able to use try/except with the prompting you listed to keep asking for an integer like it does when entering a value lower than 1? Also is the underscore in the for statement another way to declare a counter without assigning a variable there?

          – P-Sides
          Nov 29 '18 at 22:25













          @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

          – cdlane
          Nov 29 '18 at 23:56





          @P-Sides, the numinput() method has its own logic to handle some of the deviant cases -- since I set 1 as a minimum we can expect a positive number or None, never a negative. It does of course return a float so we have to deal with that. The underscore is a valid Python variable which by convention we use as a "don't care" variable. Here we want the loop to run but don't need the counter. (When using Python interactively, the underscore always contains the result of the last expression you entered.)

          – cdlane
          Nov 29 '18 at 23:56













          Ok thank you, this satisfies the original intent of the small program.

          – P-Sides
          Nov 30 '18 at 17:37





          Ok thank you, this satisfies the original intent of the small program.

          – P-Sides
          Nov 30 '18 at 17:37




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53527194%2fstate-clearing-in-python-turtle%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

          Calculate evaluation metrics using cross_val_predict sklearn

          Insert data from modal to MySQL (multiple modal on website)