Communication between privileged (function) and non-privileged (GUI) python script on macOS

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












Ok, so I am creating my own macOS cleaning app. Something like OnyX but then open-source and python based.



The removal process requires administrative privileges but since I have read that it is usually considered best practice to not run your entire GUI via sudo, I am now in the process of separating the GUI from the actual removal process.



For both aesthetics and security, when I launch the actual deletion process I want to ask the user for his password via macOS's native GUI screen. That way, I can prevent having to store the password in a variable and it just looks & feels better.



In it's most basic form my current setup thus consists of 2 python scripts:




  • Script1: A non-priviliged GUI (wx-based)


  • Script2: A priviliged deletion script

Script2 is initiated by Script1, and I need it to communicate back to Script1.



The idea is that if Script2 has to delete for example 100 files it needs to report back after each file so that the wx-Progressbar contained in Script1 can be updated accordingly.



In its most basic and stripped form my current working proof-of-concept looks like this:



Script1



Important: The line with the launch-command is commented out because it somehow messed up the code-layout here on StackExchange, but if you want to tryout the code it should be un-commented.



from pathlib import Path
import subprocess
import sys
import io
import shlex
from threading import Thread
import time

class LaunchDeletionProcess(Thread):

def __init__(self, nr_of_steps):

self.nr_of_steps = nr_of_steps
Thread.__init__(self)

def run(self):

#launch_command = r"""/usr/bin/osascript -e 'do shell script "/usr/local/bin/python3.6 -u /path/to/script2 """ + str(self.nr_of_steps) + """" with prompt "Sart Deletion Process " with administrator privileges'"""
split_command = shlex.split(launch_command)

print("Thread 1 started")
testprogram = subprocess.Popen(split_command)
testprogram.wait()

class ReadStatus(Thread):

def __init__(self, nr_of_steps):

self.nr_of_steps = nr_of_steps
Thread.__init__(self)

def run(self):

print("Thread 2 started")

check_status_file = Path("/path/to/statusfile.txt")

while not check_status_file.is_file():
time.sleep(1)

if check_status_file.is_file():
nr = 0

while nr < self.nr_of_steps:
time.sleep(1)
with open("/path/to/statusfile.txt", "r") as status_file:
status = status_file.read()
print("Current status = ", status)
nr += 1

else:
pass

if __name__ == "__main__":

nr_of_steps = 100
thread1 = LaunchDeletionProcess(nr_of_steps)
thread2 = ReadStatus(nr_of_steps)
thread1.start()
thread2.start()


Script2



import time
import sys
import os

nr_of_lines = int((sys.argv)[1])

print("nr of lines = ", nr_of_lines)

for i in range(nr_of_lines):
with open("/path/to/statusfile.txt", "w") as status_file:
status_file.write(str(i))
time.sleep(1)
print(i)

os.remove("/path/to/statusfile.txt")

sys.exit()


As you might have noticed my current setup uses a textfile to communicate between the two scripts. I am wondering if there is a better (performance wise: so more efficient, etc.), more pythonic, or more secure solution? Like, could I use multithreading for this somehow maybe? Just guessing..



Earlier attempts I've made, made use of stdin & stdout to communicate, but because Script2 is now called via osascript (needed in order to get the native GUI pop-up for administrative privileges) it is run in a non-interactive shell, thus any method using stdout won't work properly.







share|improve this question

























    up vote
    1
    down vote

    favorite












    Ok, so I am creating my own macOS cleaning app. Something like OnyX but then open-source and python based.



    The removal process requires administrative privileges but since I have read that it is usually considered best practice to not run your entire GUI via sudo, I am now in the process of separating the GUI from the actual removal process.



    For both aesthetics and security, when I launch the actual deletion process I want to ask the user for his password via macOS's native GUI screen. That way, I can prevent having to store the password in a variable and it just looks & feels better.



    In it's most basic form my current setup thus consists of 2 python scripts:




    • Script1: A non-priviliged GUI (wx-based)


    • Script2: A priviliged deletion script

    Script2 is initiated by Script1, and I need it to communicate back to Script1.



    The idea is that if Script2 has to delete for example 100 files it needs to report back after each file so that the wx-Progressbar contained in Script1 can be updated accordingly.



    In its most basic and stripped form my current working proof-of-concept looks like this:



    Script1



    Important: The line with the launch-command is commented out because it somehow messed up the code-layout here on StackExchange, but if you want to tryout the code it should be un-commented.



    from pathlib import Path
    import subprocess
    import sys
    import io
    import shlex
    from threading import Thread
    import time

    class LaunchDeletionProcess(Thread):

    def __init__(self, nr_of_steps):

    self.nr_of_steps = nr_of_steps
    Thread.__init__(self)

    def run(self):

    #launch_command = r"""/usr/bin/osascript -e 'do shell script "/usr/local/bin/python3.6 -u /path/to/script2 """ + str(self.nr_of_steps) + """" with prompt "Sart Deletion Process " with administrator privileges'"""
    split_command = shlex.split(launch_command)

    print("Thread 1 started")
    testprogram = subprocess.Popen(split_command)
    testprogram.wait()

    class ReadStatus(Thread):

    def __init__(self, nr_of_steps):

    self.nr_of_steps = nr_of_steps
    Thread.__init__(self)

    def run(self):

    print("Thread 2 started")

    check_status_file = Path("/path/to/statusfile.txt")

    while not check_status_file.is_file():
    time.sleep(1)

    if check_status_file.is_file():
    nr = 0

    while nr < self.nr_of_steps:
    time.sleep(1)
    with open("/path/to/statusfile.txt", "r") as status_file:
    status = status_file.read()
    print("Current status = ", status)
    nr += 1

    else:
    pass

    if __name__ == "__main__":

    nr_of_steps = 100
    thread1 = LaunchDeletionProcess(nr_of_steps)
    thread2 = ReadStatus(nr_of_steps)
    thread1.start()
    thread2.start()


    Script2



    import time
    import sys
    import os

    nr_of_lines = int((sys.argv)[1])

    print("nr of lines = ", nr_of_lines)

    for i in range(nr_of_lines):
    with open("/path/to/statusfile.txt", "w") as status_file:
    status_file.write(str(i))
    time.sleep(1)
    print(i)

    os.remove("/path/to/statusfile.txt")

    sys.exit()


    As you might have noticed my current setup uses a textfile to communicate between the two scripts. I am wondering if there is a better (performance wise: so more efficient, etc.), more pythonic, or more secure solution? Like, could I use multithreading for this somehow maybe? Just guessing..



    Earlier attempts I've made, made use of stdin & stdout to communicate, but because Script2 is now called via osascript (needed in order to get the native GUI pop-up for administrative privileges) it is run in a non-interactive shell, thus any method using stdout won't work properly.







    share|improve this question





















      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      Ok, so I am creating my own macOS cleaning app. Something like OnyX but then open-source and python based.



      The removal process requires administrative privileges but since I have read that it is usually considered best practice to not run your entire GUI via sudo, I am now in the process of separating the GUI from the actual removal process.



      For both aesthetics and security, when I launch the actual deletion process I want to ask the user for his password via macOS's native GUI screen. That way, I can prevent having to store the password in a variable and it just looks & feels better.



      In it's most basic form my current setup thus consists of 2 python scripts:




      • Script1: A non-priviliged GUI (wx-based)


      • Script2: A priviliged deletion script

      Script2 is initiated by Script1, and I need it to communicate back to Script1.



      The idea is that if Script2 has to delete for example 100 files it needs to report back after each file so that the wx-Progressbar contained in Script1 can be updated accordingly.



      In its most basic and stripped form my current working proof-of-concept looks like this:



      Script1



      Important: The line with the launch-command is commented out because it somehow messed up the code-layout here on StackExchange, but if you want to tryout the code it should be un-commented.



      from pathlib import Path
      import subprocess
      import sys
      import io
      import shlex
      from threading import Thread
      import time

      class LaunchDeletionProcess(Thread):

      def __init__(self, nr_of_steps):

      self.nr_of_steps = nr_of_steps
      Thread.__init__(self)

      def run(self):

      #launch_command = r"""/usr/bin/osascript -e 'do shell script "/usr/local/bin/python3.6 -u /path/to/script2 """ + str(self.nr_of_steps) + """" with prompt "Sart Deletion Process " with administrator privileges'"""
      split_command = shlex.split(launch_command)

      print("Thread 1 started")
      testprogram = subprocess.Popen(split_command)
      testprogram.wait()

      class ReadStatus(Thread):

      def __init__(self, nr_of_steps):

      self.nr_of_steps = nr_of_steps
      Thread.__init__(self)

      def run(self):

      print("Thread 2 started")

      check_status_file = Path("/path/to/statusfile.txt")

      while not check_status_file.is_file():
      time.sleep(1)

      if check_status_file.is_file():
      nr = 0

      while nr < self.nr_of_steps:
      time.sleep(1)
      with open("/path/to/statusfile.txt", "r") as status_file:
      status = status_file.read()
      print("Current status = ", status)
      nr += 1

      else:
      pass

      if __name__ == "__main__":

      nr_of_steps = 100
      thread1 = LaunchDeletionProcess(nr_of_steps)
      thread2 = ReadStatus(nr_of_steps)
      thread1.start()
      thread2.start()


      Script2



      import time
      import sys
      import os

      nr_of_lines = int((sys.argv)[1])

      print("nr of lines = ", nr_of_lines)

      for i in range(nr_of_lines):
      with open("/path/to/statusfile.txt", "w") as status_file:
      status_file.write(str(i))
      time.sleep(1)
      print(i)

      os.remove("/path/to/statusfile.txt")

      sys.exit()


      As you might have noticed my current setup uses a textfile to communicate between the two scripts. I am wondering if there is a better (performance wise: so more efficient, etc.), more pythonic, or more secure solution? Like, could I use multithreading for this somehow maybe? Just guessing..



      Earlier attempts I've made, made use of stdin & stdout to communicate, but because Script2 is now called via osascript (needed in order to get the native GUI pop-up for administrative privileges) it is run in a non-interactive shell, thus any method using stdout won't work properly.







      share|improve this question











      Ok, so I am creating my own macOS cleaning app. Something like OnyX but then open-source and python based.



      The removal process requires administrative privileges but since I have read that it is usually considered best practice to not run your entire GUI via sudo, I am now in the process of separating the GUI from the actual removal process.



      For both aesthetics and security, when I launch the actual deletion process I want to ask the user for his password via macOS's native GUI screen. That way, I can prevent having to store the password in a variable and it just looks & feels better.



      In it's most basic form my current setup thus consists of 2 python scripts:




      • Script1: A non-priviliged GUI (wx-based)


      • Script2: A priviliged deletion script

      Script2 is initiated by Script1, and I need it to communicate back to Script1.



      The idea is that if Script2 has to delete for example 100 files it needs to report back after each file so that the wx-Progressbar contained in Script1 can be updated accordingly.



      In its most basic and stripped form my current working proof-of-concept looks like this:



      Script1



      Important: The line with the launch-command is commented out because it somehow messed up the code-layout here on StackExchange, but if you want to tryout the code it should be un-commented.



      from pathlib import Path
      import subprocess
      import sys
      import io
      import shlex
      from threading import Thread
      import time

      class LaunchDeletionProcess(Thread):

      def __init__(self, nr_of_steps):

      self.nr_of_steps = nr_of_steps
      Thread.__init__(self)

      def run(self):

      #launch_command = r"""/usr/bin/osascript -e 'do shell script "/usr/local/bin/python3.6 -u /path/to/script2 """ + str(self.nr_of_steps) + """" with prompt "Sart Deletion Process " with administrator privileges'"""
      split_command = shlex.split(launch_command)

      print("Thread 1 started")
      testprogram = subprocess.Popen(split_command)
      testprogram.wait()

      class ReadStatus(Thread):

      def __init__(self, nr_of_steps):

      self.nr_of_steps = nr_of_steps
      Thread.__init__(self)

      def run(self):

      print("Thread 2 started")

      check_status_file = Path("/path/to/statusfile.txt")

      while not check_status_file.is_file():
      time.sleep(1)

      if check_status_file.is_file():
      nr = 0

      while nr < self.nr_of_steps:
      time.sleep(1)
      with open("/path/to/statusfile.txt", "r") as status_file:
      status = status_file.read()
      print("Current status = ", status)
      nr += 1

      else:
      pass

      if __name__ == "__main__":

      nr_of_steps = 100
      thread1 = LaunchDeletionProcess(nr_of_steps)
      thread2 = ReadStatus(nr_of_steps)
      thread1.start()
      thread2.start()


      Script2



      import time
      import sys
      import os

      nr_of_lines = int((sys.argv)[1])

      print("nr of lines = ", nr_of_lines)

      for i in range(nr_of_lines):
      with open("/path/to/statusfile.txt", "w") as status_file:
      status_file.write(str(i))
      time.sleep(1)
      print(i)

      os.remove("/path/to/statusfile.txt")

      sys.exit()


      As you might have noticed my current setup uses a textfile to communicate between the two scripts. I am wondering if there is a better (performance wise: so more efficient, etc.), more pythonic, or more secure solution? Like, could I use multithreading for this somehow maybe? Just guessing..



      Earlier attempts I've made, made use of stdin & stdout to communicate, but because Script2 is now called via osascript (needed in order to get the native GUI pop-up for administrative privileges) it is run in a non-interactive shell, thus any method using stdout won't work properly.









      share|improve this question










      share|improve this question




      share|improve this question









      asked Apr 4 at 20:03









      Montmons

      1062




      1062

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          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: "196"
          ;
          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',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191275%2fcommunication-between-privileged-function-and-non-privileged-gui-python-scri%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191275%2fcommunication-between-privileged-function-and-non-privileged-gui-python-scri%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?