0

I have yet another question about Python multiprocessing. I have a module that creates a Process and just runs in a while True loop. This module is meant to be enabled/disabled from another Python module. That other module will import the first one once and is also run as a process.

How would I better implement this?

so for a reference:

#foo.py

def foo():
  while True:
    if enabled:
      #do something

p = Process(target=foo)
p.start()

and imagine second module to be something like that:

#bar.py
import foo, time

def bar():
  while True:
    foo.enable()
    time.sleep(10)
    foo.disable()

Process(target=bar).start()

Constantly running a process checking for condition inside a loop seems like a waste, but I would gladly accept the solution that just lets me set the enabled value from outside. Ideally I would prefer to be able to terminate and restart the process, again from outside of this module. From my understanding, I would use a Queue to pass commands to the Process. If it is indeed just that, can someone show me how to set it up in a way that I can add something to the queue from a different module.

Can this even be easily done with Python or is it time to abandon hope and switch to something like C or Java

akalikin
  • 1,071
  • 12
  • 35
  • What about that ? http://stackoverflow.com/questions/2804287/pausing-a-process – FunkySayu Aug 05 '15 at 11:13
  • Or maybe this one is better for what you are looking for : http://stackoverflow.com/questions/28812011/how-to-pause-multiprocessing-process-in-python – FunkySayu Aug 05 '15 at 11:14

1 Answers1

2

I purposed in comment two different approches :

  • using a shared variable from multiprocessing.Value
  • pause / resume the process with signals

Control by sharing a variable

def target_process_1(run_statement):
    while True:
        if run_statement.value:
            print "I'm running !"
            time.sleep(1)

def target_process_2(run_statement):
    time.sleep(3)
    print "Stoping"
    run_statement.value = False
    time.sleep(3)
    print "Resuming"
    run_statement.value = True

if __name__ == "__main__":
    run_statement = Value("i", 1)

    process_1 = Process(target=target_process_1, args=(run_statement,))
    process_2 = Process(target=target_process_2, args=(run_statement,))

    process_1.start()
    process_2.start()

    time.sleep(8)
    process_1.terminate()
    process_2.terminate()

Control by sending a signal

from multiprocessing import Process
import time
import os, signal

def target_process_1():
    while True:
        print "Running !"
        time.sleep(1)

def target_process_2(target_pid):
    time.sleep(3)
    os.kill(target_pid, signal.SIGSTOP)
    time.sleep(3)
    os.kill(target_pid, signal.SIGCONT)

if __name__ == "__main__":
    process_1 = Process(target=target_process_1)
    process_1.start()

    process_2 = Process(target=target_process_2, args=(process_1.pid,))
    process_2.start()

    time.sleep(8)

    process_1.terminate()
    process_2.terminate()

Side note: if possible do not run a while True.


EDIT: if you want to manage your process in two different files, supposing you want to use a control by sharing a variable, this is a way to do.

# file foo.py

from multiprocessing import Value, Process
import time

__all__ = ['start', 'stop', 'pause', 'resume']

_statement = None
_process = None

def _target(run_statement):
    """ Target of the foo's process """
    while True:
        if run_statement.value:
            print "I'm running !"
            time.sleep(1)

def start():
    global _process, _statement
    _statement = Value("i", 1)
    _process = Process(target=_target,  args=(_statement,))
    _process.start()

def stop():
    global _process, _statement
    _process.terminate()
    _statement, _process = None, _process

def enable():
    _statement.value = True

def disable():
    _statement.value = False
FunkySayu
  • 7,641
  • 10
  • 38
  • 61
  • This is a good solution, although I'm not sure how this can be implemented in two different files – akalikin Aug 05 '15 at 12:36
  • thanks! So what does bar.py do? Is it as simple as importing foo and then using enable(), disable() etc? – akalikin Aug 05 '15 at 13:16
  • The `bar.py` script is nearly the same that yours, except you must run `foo.start()` somewhere in your program before using `foo.{dis|en}able()`. – FunkySayu Aug 05 '15 at 13:31