title: ModuleNotFoundError: No module named 'ui'
body: <p>I am trying to run the following script from the pythonista drawing app example in IDLE on my macbook, but am getting the error &quot;ModuleNotFoundError: No module named 'ui'&quot;</p>
  <p>Website for the UI itself:  <a href="https://omz-software.com/pythonista/docs/ios/ui.html" rel="nofollow noreferrer">https://omz-software.com/pythonista/docs/ios/ui.html</a></p>
  <p>I can't seem to find any install procedures for this ui and would appreciate any help, as it runs on my ipad so just want to see how it runs on my mac as well.</p>
  <pre><code>import ui
  import photos
  import console
  
  # The PathView class is responsible for tracking
  # touches and drawing the current stroke.
  # It is used by SketchView.
  
  class PathView (ui.View):
      def __init__(self, frame):
          self.frame = frame
          self.flex = 'WH'
          self.path = None
          self.action = None
      
      def touch_began(self, touch):
          x, y = touch.location
          self.path = ui.Path()
          self.path.line_width = 8.0
          self.path.line_join_style = ui.LINE_JOIN_ROUND
          self.path.line_cap_style = ui.LINE_CAP_ROUND
          self.path.move_to(x, y)
      
      def touch_moved(self, touch):
          x, y = touch.location
          self.path.line_to(x, y)
          self.set_needs_display()
      
      def touch_ended(self, touch):
          # Send the current path to the SketchView:
          if callable(self.action):
              self.action(self)
          # Clear the view (the path has now been rendered
          # into the SketchView's image view):
          self.path = None
          self.set_needs_display()
      
      def draw(self):
          if self.path:
              self.path.stroke()
  
  # The main SketchView contains a PathView for the current
  # line and an ImageView for rendering completed strokes.
  # It also manages the 'Clear' and 'Save' ButtonItems that
  # are shown in the title bar.
  
  class SketchView (ui.View):
      def __init__(self, width=1024, height=1024):
          self.bg_color = 'white'
          iv = ui.ImageView(frame=(0, 0, width, height))
          pv = PathView(frame=self.bounds)
          pv.action = self.path_action
          self.add_subview(iv)
          self.add_subview(pv)
          save_button = ui.ButtonItem()
          save_button.title = 'Save Image'
          save_button.action = self.save_action
          clear_button = ui.ButtonItem()
          clear_button.title = 'Clear'
          clear_button.tint_color = 'red'
          clear_button.action = self.clear_action
          self.right_button_items = [save_button, clear_button]
          self.image_view = iv
      
      def path_action(self, sender):
          path = sender.path
          old_img = self.image_view.image
          width, height = self.image_view.width, self.image_view.height
          with ui.ImageContext(width, height) as ctx:
              if old_img:
                  old_img.draw()
              path.stroke()
              self.image_view.image = ctx.get_image()
      
      def clear_action(self, sender):
          self.image_view.image = None
      
      def save_action(self, sender):
          if self.image_view.image:
              # We draw a new image here, so that it has the current
              # orientation (the canvas is quadratic).
              with ui.ImageContext(self.width, self.height) as ctx:
                  self.image_view.image.draw()
                  img = ctx.get_image()
                  photos.save_image(img)
                  console.hud_alert('Saved')
          else:
              console.hud_alert('No Image', 'error')
      
  # We use a square canvas, so that the same image
  # can be used in portrait and landscape orientation.
  w, h = ui.get_screen_size()
  canvas_size = max(w, h)
  
  sv = SketchView(canvas_size, canvas_size)
  sv.name = 'Sketch'
  sv.present('fullscreen')
  </code></pre>