2

I have two scripts inside a bigger system I'm developing. Lets call one foo.py and the other one bar.py.

foo creates files that bar will afterwards read and delete. Now, if foo is running and working on a file, bar will mess things up by working on the same file before foo is finished.

foo and bar get started automatically by other stuff, not manually by someone that runs them. How can I make sure that, if foo is working on a file, bar will not start?

I have thought about editing both of them so that foo writes a 1 to a text file at the beginning of the execution and a 0 when it finishes, and to make bar read the text file to check wheter it can start. But I'm not really sure this is the most elegant solution, and also I don't want to block bar if foo ever fails in the middle of execution, leaving the file at 1.

Pablo M
  • 326
  • 2
  • 7
  • Can't you execute foo in a subprocess and make bar wait for foo to finish (by success or fail) using `Popen.poll()`? Also see https://stackoverflow.com/q/43274476/2923755 – niCk cAMel Nov 11 '17 at 16:47
  • Have you looked into file locking? –  Nov 11 '17 at 17:13
  • Newbie here, haven't header about subprocesses or file locking. Gonna do my own research, but, could you guys point to any good sources? – Pablo M Nov 12 '17 at 17:42
  • @PabloM start by searching for `Popen`. There you will find info on both `subprocess` and `poll` – niCk cAMel Nov 12 '17 at 23:39

3 Answers3

1

You can use subprocess

In your main file:

import subprocess


def main():
    p = subprocess.Popen(['python', 'foo.py'])
    res = p.wait()
    if res == 0:
        print("foo did ok")
        # execute bar.py
    else:
        print("foo failed along the way")

In foo.py, make sure to exit with code 0 if everything went fine: exit(0) (this will be returned to res in main script).

You can also use poll() if you want to do other stuff while waiting for foo to finish.

def main():
    p = subprocess.Popen(['python', 'foo.py'])

    while not p.poll()==0:
        print("wait for foo")
        #do some other magic. but make sure to have a break condition
        # e.g. if foo takes too long.
niCk cAMel
  • 869
  • 1
  • 10
  • 26
0

A possible strategy :

  • foo build todo.foo.
  • it renames it todo.bar when done.
  • bar look after todo.bar, compute it and delete it when done.
B. M.
  • 18,243
  • 2
  • 35
  • 54
0
import fcntl

pid_file = 'mysoftware.pid'
fp = open(pid_file, 'w')
try:
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    # another instance is running
    print("already running")
    sys.exit(1)

this works for me.

Ando
  • 49
  • 1
  • 8