0

I have a script (Python) that uses subprocess to call another script. The parent script writes to the console and a log file at the same time (I used the code from the accepted answer to this question to split the output), but the child process print statements are only going to stdout, not to the log file.

I do know why this is: the subprocess has stdout set to normal stdout, not the special tee object that the parent process has. I tried passing the tee object as an argument to the subprocess, but I learned the hard way that you cannot pass objects as arguments to subprocesses. My backup plan was to pass in the path string for the file to write to, and then have the subprocess make its own tee object with the same file.

My question is, if both processes are writing to the same file at the same time, will the output be messed up? I'm using open("file", 'w') in the parent process, and this is called first, and I'm using open("file", 'a') in the child process. Hypothetically, the file should contain the output of the print statements in the correct order, because appending to a file with 'a' means that the lines will always be added to what is currently the end of the file, will it not? Or are there rules about opening a file that prevent it from being opened by 2 processes at the same time?

POST_TEST: after doing some tests myself, I found the following: -You are allowed to open("file", 'w') multiple times in a row -You are allowed to open("file", 'w') and then open("file", 'a') -In the first case, the child process overwrites the file completely. -In the second case, the order is not correct, and some output seems to be lost.

My new question then, is what alternative solution should I use to write to a file from both the parent and child process at the same time, without getting lines out of order or overlapping?

Community
  • 1
  • 1
Eliezer Miron
  • 388
  • 5
  • 18

2 Answers2

0

Thank you Bamar for the suggestions: using 'a' for both the first and second open() works. If you need to do this for a file that already exists, you can use file.truncate() to empty the file before appending to it.

Community
  • 1
  • 1
Eliezer Miron
  • 388
  • 5
  • 18
  • It is not guaranteed that all writes are at the end on all systems if the file is opened in `'a'` mode. It is not guaranteed that larges `write()`s are atomic (the output from several processes may interleave). – jfs Jul 01 '16 at 14:15
0

Opening a file in 'w' mode truncates the file (as documented). Opening a file in 'a' mode may work on some systems. POSIX says for O_APPEND flag:

If set, the file offset shall be set to the end of the file prior to each write.

write()s that are larger than PIPE_BUF may interleave:

POSIX.1-2008 does not say whether write requests for more than {PIPE_BUF} bytes are atomic, but requires that writes of {PIPE_BUF} or fewer bytes shall be atomic.


Q: what alternative solution should I use to write to a file from both the parent and child process at the same time, without getting lines out of order or overlapping?

Open the files using line-buffering mode (1), to flush the internal buffer at the end of each line -- it should preserve the approximate relative order of the lines. If lines are less than PIPE_BUF (4096 bytes on my system) then they should not "overlap".


The subprocess may write data to its standard output and your parent Python process may write it to a file in any order you like. See how teed_call() function is implemented.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670