omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Console output from ui

    Pythonista
    3
    6
    3821
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • charmaex
      charmaex last edited by

      I wrote a script that is controlled via an ui and outputs what it does through the console.

      My problem is that it doesn't output the data in realtime.
      My code works like the following example.
      The time.sleep(5) is just some time consuming task.
      I would like to have an output like this

      a
      b
      waiting 5 seconds
      c
      d

      Instead the output is

      a
      waiting 5 seconds
      b
      c
      d

      # coding: utf-8
      
      import ui, time, tempfile
      
      ui_file = '[{"selected" : false,"frame" : "{{0, 0}, {240, 240}}","class" : "View","nodes" : [{"selected" : true,"frame" : "{{75, 49}, {80, 32}}","class" : "Button","nodes" : [],"attributes" : {"action" : "button","frame" : "{{80, 104}, {80, 32}}","title" : "Button","class" : "Button","uuid" : "269E121F-FCD6-478B-B6CD-2F2C2D3E2ED8","font_size" : 15,"name" : "button1"}}],"attributes" : {"enabled" : true,"background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)","tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)","border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)","flex" : ""}}]'
      
      def button(sender):
      	print 'b'
      	time.sleep(5)
      	print 'c'
      	
      open('Test_abcd.pyui', 'w').write(ui_file)
      
      print 'a'
      v = ui.load_view('Test_abcd')
      v.present('sheet')
      v.wait_modal()
      print 'd'
      
      1 Reply Last reply Reply Quote 0
      • ccc
        ccc last edited by ccc

        Try replacing time.sleep(5) with ui.delay(None, 5)... I am not sure if it will do the right thing or not.

        If not, you could create a function called print_c() that does print('c') and then do ui.delay(print_c, 5).

        1 Reply Last reply Reply Quote 0
        • charmaex
          charmaex last edited by

          Thanks for your reply.

          Maybe my example was a bit to simple.

          time.sleep(5) is a placeholder for downloading files (which takes some time).
          print c indicates, that the download is finished. So this should follow the sleep.
          My problem is that the b isn't printed before the download starts.

          If I only run button() everything works fine. Running button() via the ui prints b and c at the same time (after 5 secs).
          I want it to print b, work, print c.

          1 Reply Last reply Reply Quote 0
          • JonB
            JonB last edited by JonB

            The typical way you handle long running callbacks is to use the ui.in_background decorator. Remember, a button action needs to exit wuickly, or the ui appears frozen.

            However, that does not work with wait_modal -- not sure if that is a bug or a documentation quirk. Basically, wait_modal seems to use the same single background thread, so anything backgrounded gets run after the dialog is closed.

            The solution is to use ui.delay to launch another function containing your slow process.

            def button(sender):
               print 'b'
               def other():
                	time.sleep(5) # call to some time consuming task
                	print 'c'
               ui.delay(other,0.01) #easy way to launch a new thread
            

            Another option would be to use this run_async decorator on you action, which actually runs the function a background thread, as opposed to queuing it up..

            def run_async(func):
               from threading import Thread
               from functools import wraps
            
               @wraps(func)
               def async_func(*args, **kwargs):
                  func_hl = Thread(target = func, args = args, kwargs = kwargs)
                  func_hl.start()
                  return func_hl
            
               return async_func
            
            1 Reply Last reply Reply Quote 0
            • ccc
              ccc last edited by

              @JonB gave better advise than I did...

              import ui
              def download():
                  print('download')
              print('a')
              ui.delay(download, 0.02)
              print('b')
              
              1 Reply Last reply Reply Quote 0
              • charmaex
                charmaex last edited by

                Thank you all for your help.

                After some fumbling around I decided to close the UI and then start the action.
                This was the easiest way without having to change much code :)

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors