2

I'm writing a parser in Python that outputs a bunch of database rows to standard out. In order for the DB to process them properly, each row needs to be fully printed to the console. I'm trying to prevent interrupts from making the print command stop halfway through printing a line.

I tried the solution that recommended using a signal handler override, but this still doesn't prevent the row from being partially printed when the program is interrupted. (I think the WRITE system call is cancelled to handle the interrupt).

I thought that the problem was solved by issue 10956 but I upgraded to Python 2.7.5 and the problem still happens.

You can see for yourself by running this example:

# Writer
import signal
interrupted = False
def signal_handler(signal, frame):
    global interrupted
    iterrupted = True

signal.signal(signal.SIGINT, signal_handler)
while True:
    if interrupted:
        break
    print '0123456789'

In a terminal:

$ mkfifo --mode=0666 pipe
$ python writer.py > pipe

In another terminal:

$ cat pipe

Then Ctrl+C the first terminal. Some of the time the second terminal will end with an incomplete sequence of characters.

Is there any way of ensuring that full lines are written?

Community
  • 1
  • 1
frank
  • 1,322
  • 1
  • 10
  • 28

2 Answers2

2

This seems less like an interrupt problem per se then a buffering issue. If I make a small change to your code, I don't get the partial lines.

# Writer
import sys

while True:
    print '0123456789'
    sys.stdout.flush()
Wm Annis
  • 123
  • 4
  • 1
    The partial writes issue does seem to be primarly a buffering issue. However the author is also correct that writes can be interrupted. In C puts/fputs have a special EINTR return code to notify the user that a write failed due to being interrupted. This could result in rejected or partial writes depending on your system. – Andrew Johnson Sep 16 '14 at 03:24
0

It sounds like you don't really want to catch a signal but rather block it temporarily. This is supported by some *nix flavours. However Python explicitly does not support this.

You can write a C wrapper for sigmasks or look for a library. However if you are looking for a portable solution...

Andrew Johnson
  • 3,078
  • 1
  • 18
  • 24