2.4 SubProcessing

2.4.1 SubprocessTask

SubprocessTask is a way to run external programs. It is just a wrapper for subprocess.Popen.

doc8.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from baelfire.dependencies import AlwaysTrue
from baelfire.task import SubprocessTask


class SimpleProccess(SubprocessTask):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        self.popen('echo "something"')

if __name__ == '__main__':
    SimpleProccess().run()
$ python doc8.py
something

All args from SubprocessTask.popen is passed to subprocess.Popen, but the shell argument is from default, which is set to True. If you want to change that, just override _set_default_args method.

doc9.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from baelfire.dependencies import AlwaysTrue
from baelfire.task import SubprocessTask


class SimpleProccess(SubprocessTask):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        self.popen(['echo', 'something'])

    def _set_default_args(self, args, kwargs):
        kwargs.setdefault('shell', False)
        return args, kwargs


if __name__ == '__main__':
    SimpleProccess().run()
$ python doc9.py
something

2.4.2 Pid dependencies

baelfire.dependencies.pid.PidIsRunning and baelfire.dependencies.pid.PidIsNotRunning are dependencies which are designed to work with pid numbers. PidIsRunning will indicate build if pid is already running. PidIsNotRunning will only trigger build if pid is not running. PidIsRunning and PidIsNotRunning init method will accept pid in 3 ways:

  • pid - as a raw number
  • pid_file_name - pid file name from .paths
  • pid_file_path - raw pif file path
doc10.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from subprocess import Popen

from baelfire.dependencies.dependency import AlwaysTrue
from baelfire.dependencies.pid import PidIsNotRunning
from baelfire.dependencies.pid import PidIsRunning
from baelfire.task import Task
from baelfire.task.process import SubprocessTask

proc = Popen(['sleep 0.1'], shell=True)


class ExampleProccess(SubprocessTask):

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        self.popen(['yes'])


class RunWhenSleepIsRunning(Task):

    def create_dependecies(self):
        self.build_if(PidIsRunning(proc.pid))

    def build(self):
        print("sleep is still running...")


class RunWhenSleepIsNotRunning(Task):

    def create_dependecies(self):
        self.build_if(PidIsNotRunning(proc.pid))

    def build(self):
        print("sleep is not running!")


if __name__ == '__main__':
    RunWhenSleepIsRunning().run()
    RunWhenSleepIsNotRunning().run()
    proc.wait()

    print("- After Termination")
    RunWhenSleepIsRunning().run()
    RunWhenSleepIsNotRunning().run()
$ python doc10.py
sleep is still running...
- After Termination
sleep is not running!

2.4.3 Ignore abort error

SubprocessTask has a setting named IGNORE_ABORT which will change behaviour of the error mechanism. When this var is set to True (default) and the task will be aborted (for example, by using CTRL+C), then no exception will be raised and the command will just be ended. But if we set this to False, then the command will raise a CommandAbort error.

doc15.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from baelfire.dependencies import AlwaysTrue
from baelfire.task import SubprocessTask


class SimpleProccess(SubprocessTask):
    IGNORE_ABORT = False

    def create_dependecies(self):
        self.build_if(AlwaysTrue())

    def build(self):
        self.popen('echo "something"')

if __name__ == '__main__':
    SimpleProccess().run()