1

I have a Python script:

import subprocess

subprocess.run(['black', 'src'])

I would like to tell if the command run by subprocess modified any file in the folder src - so, I'd like my script to look like this:

import subprocess

subprocess.run(['black', 'src'])
mutated = <???>

How can I detect whether any file in the directory src changed after the subprocess.run command, and if so assign True to mutated?

EDIT

Using os.path.getmtime isn't working for me:

(Pdb) os.path.getmtime(str(arg))
1596263725.3222768
(Pdb) subprocess.run(['black', str(arg), '--line-length=5'])
reformatted /tmp/tmp7e7suv4e/tests/data/clean_notebook   .py
reformatted /tmp/tmp7e7suv4e/tests/data/notebook_for_testing   .py
reformatted /tmp/tmp7e7suv4e/tests/data/notebook_for_testing_copy   .py
reformatted /tmp/tmp7e7suv4e/tests/data/notebook_starting_with_md   .py
All done! ✨ 🍰 ✨
4 files reformatted, 2 files left unchanged.
CompletedProcess(args=['black', '/tmp/tmp7e7suv4e/tests', '--line-length=5'], returncode=0)
(Pdb) os.path.getmtime(str(arg))
1596263725.3222768
6
  • What do you mean by "changed"? New files added or deleted? Touched modification time? Once you have a clear definition, you should be able to figure out what to check pretty easily. Commented Jul 31, 2020 at 17:10
  • @MadPhysicist what I mean is whether any files were modified Commented Jul 31, 2020 at 17:18
  • Add that to your question. Also, please use valid python syntax. You can't just have a return like that. Commented Jul 31, 2020 at 17:18
  • You need to provide ,arg in the update, and don't do Edit. Just make the question self contained. Commented Aug 1, 2020 at 14:03
  • Also, why are you running in /tmp. That sounds fishy in and of itself. Commented Aug 1, 2020 at 14:03

1 Answer 1

1

Not the most reliable approach, but you can get the system time immediately before running the subprocess, then compare it to the modification time of the folder.

from time import time
from os.path import getmtime

before = time()
# Run subprocess
mutated = getmtime('src') > before

This approach is a bit unreliable, for example if your system clock gets reset between reboots or something. A better way would be to compare modification times on the folder:

from os.path import getmtime

before = getmtime('src')
# Run subprocess
mutated = getmtime('src') != before

This works because on normal file systems, "modifying" a file usually involves rewriting it, which means updating the directory entry for it, which in turn means that the directory itself is modified. An example of a program that does not do that is touch. If you run into a program that does not do it that way, you can always check the modification times of the individual files in the folder in the same way:

from os import listdir
from os.path import join, getmtime

def mtimes(path):
    return {fname: getmtime(join(path, fname)) for fname in os.listdir(path)}

before = mtimes('src')
# Run subprocess
mutated = mtimes('src') == before

Using == on dicts automatically checks that all keys are equal (i.e., if files were added or deleted), and that all corresponding modification time values are equal.

It is conceivable that you will get some false positives this way if another process accesses the folder, but virtually impossible to get false negatives, unless someone explicitly messes with the modification times.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer - this isn't quite working for me though, have update the question with output from my debugger
It seems like I need to compare the mtime for each file in os.walk(str(arg))
@ignoring_gravity. This is supposed to give to the places to look, not necessarily provide you with copy-and-pastable code. os.listdir does not process nested files. If you need to do that, make the appropriate modifications in your actual code, but you don't need to change the question for that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.