[Tutor] No file or directory error using subprocess and Popen

Jim jf_byrnes at comcast.net
Mon May 15 21:39:12 EDT 2017


On 05/15/2017 07:03 AM, Peter Otten wrote:
> Jim wrote:
>
>> I am running this on Mint 18.
>> This is the third script I have written to open and position windows in
>> workspaces. The first two work, but trying to open ebook-viewe r
>> (calibre) with a specific book produces the following error.
>> If I run the same command in the terminal it works without an error.
>>
>>
>> Exception in thread Thread-4:
>> Traceback (most recent call last):
>>    File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
>>      self.run()
>>    File "/usr/lib/python3.5/threading.py", line 862, in run
>>      self._target(*self._args, **self._kwargs)
>>    File "/home/jfb/MyProgs/Scripts/place_windows_OO_WS3.py", line 24, in
>> open_it
>>      subprocess.call([self.program])
>>    File "/usr/lib/python3.5/subprocess.py", line 557, in call
>>      with Popen(*popenargs, **kwargs) as p:
>>    File "/usr/lib/python3.5/subprocess.py", line 947, in __init__
>>      restore_signals, start_new_session)
>>    File "/usr/lib/python3.5/subprocess.py", line 1551, in _execute_child
>>      raise child_exception_type(errno_num, err_msg)
>> FileNotFoundError: [Errno 2] No such file or directory: 'ebook-viewer
>>
> /home/jfb/Documents/eBooks/Javascript/GOOGLE_SHEETS/googlespreadsheetprogramming.epub'
>>
>> Code:
>>
>> # place_windows_OO_WS3.py
>>
>> import subprocess
>> from subprocess import Popen,PIPE
>> import threading
>> import time
>>
>> class Place():
>>
>>      def __init__(self):
>>          self.programs = ['jedit', 'google-chrome', 'doublecmd',
>>          'ebook-viewer
>>
> /home/jfb/Documents/eBooks/Javascript/GOOGLE_SHEETS/googlespreadsheetprogramming.epub']
>>          self.classname = {'jedit' : 'sun-awt-X11-XFramePeer',
>>                              'google-chrome':'google-chrome',
>>                              'doublecmd':'doublecmd',
>>                              'calibre-ebook-viewer': 'libprs500'}
>>          self.open_and_move()
>>
>>      def open_it(self):
>>          subprocess.call([self.program])
>>
>>      def open_and_move(self):
>>          for self.program in self.programs:
>>              opener = threading.Thread(target=self.open_it)
>>              opener.start()
>>              time.sleep(2)
>>              p = Popen(['xdotool', 'search', '--classname',
>> self.classname[self.program]], stdout=subprocess.PIPE)
>>
>>              if self.classname[self.program] == 'sun-awt-X11-XFramePeer':
>>                  wid = str(p.stdout.read())
>>                  wid = wid[len(wid) - 11 : len(wid) - 3]
>>                  x = '0'
>>                  y = '0'
>>                  print('***jedit***')
>>              elif self.classname[self.program] == 'google-chrome':
>>                  wid = str(p.stdout.read())
>>                  wid = wid[len(wid) - 11 : len(wid) - 3]
>>                  x = '1924'
>>                  y = '0'
>>                  print('***google***')
>>              elif self.classname[self.program] == 'doublecmd':
>>                  wid = str(p.stdout.read())
>>                  wid = wid[len(wid) - 11 : len(wid) - 3]
>>                  x = '1924'
>>                  y = '537'
>>                  print('***double***')
>>              else:
>>                  wid = str(p.stdout.read())
>>                  wid = wid[len(wid) - 11 : len(wid) - 3]
>>                  x = '2540' #'1924'
>>                  y = '537'
>>                  print('***calibre***')
>>              subprocess.call(['xdotool', 'windowmove', str(wid), x, y])
>>
>> I did some googling and it seems that subprocess does not have a length
>> limit in linux. Could someone tell me how to correct the above error.
>
> Not directly related to your question, but I think you should have one
> instance of your Place class per program. That way you keep related
> information together and avoid the need to look it up in a dict or find it
> with a long chain of if ... elif ... tests. For example:
>
> # untested
> import subprocess
> import threading
> import time
>
> DELAY = 3.0  # seconds
>
>
> class Place:
>     def __init__(self, cmd, classname=None, name=None, x=0, y=0):
>         if classname is None:
>             classname = cmd[0]
>         if name is None:
>             name = cmd[0]
>
>         self.cmd = cmd
>         self.classname = classname
>         self.name = name
>         self.x = x
>         self.y = y
>
>     def open_it(self):
>         subprocess.call(self.cmd)
>
>     def open_and_move(self):
>         opener = threading.Thread(target=self.open_it)
>         opener.start()
>         time.sleep(DELAY)
>         output = subprocess.Popen(
>             ['xdotool', 'search', '--classname', self.classname],
>             stdout=subprocess.PIPE
>         ).communicate()[0]
>         wid = output.split()[-1].decode()
>         subprocess.call(
>             [
>                 'xdotool', 'windowmove',
>                 wid, str(self.x), str(self.y)
>             ]
>         )
>         print("***{}***".format(self.name))
>
> EBOOK = (
>     "/home/jfb/Documents/eBooks/Javascript/"
>     "GOOGLE_SHEETS/googlespreadsheetprogramming.epub"
> )
>
> programs = [
>     Place(["jedit"], classname="sun-awt-X11-XFramePeer"),
>     Place(["google-chrome"], x=1924),
>     Place(["doublecmd"], x=1924, y=537),
>     Place(
>         ["ebook-viewer", EBOOK],
>         classname="libprs500", name="calibre",
>         x=2540, y=537
>     )
> ]
>
> for program in programs:
>     program.open_and_move()
>
> Now when you add a new program you just append a new `Place` instance to the
> `programs` list.
>

Peter,

Thanks for the code. Once I get it working I will definitely look at 
changing my code to follow your guidelines.

Thanks,  Jim




More information about the Tutor mailing list