This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author ralph.corderoy
Recipients BreamoreBoy, Finkregh, benjamin.peterson, doko, draghuram, eric.araujo, ggenellina, marhar, nvetoshkin, r_mosaic, ralph.corderoy
Date 2012-01-28.18:31:18
SpamBayes Score 7.123027e-08
Marked as misclassified No
Message-id <1327775479.85.0.714378132553.issue1633941@psf.upfronthosting.co.za>
In-reply-to
Content
This most certainly is a bug under Unix and an annoying one.  "Since the
issue is with platform's stdio library" is wrong;  stdio is being used
incorrectly.  It would be nice to see it fixed in the 2.x line.

I've two test programs.

    $ head -42 stdin2.6 stdin3.1
    ==> stdin2.6 <==
    #! /usr/bin/python2.6

    import sys

    for l in sys.stdin:
        print repr(l)
    print 'end'

    ==> stdin3.1 <==
    #! /usr/bin/python3.1

    import sys

    for l in sys.stdin:
        print(repr(l))
    print('end')

    $

For both of them I will type "1 Enter 2 Enter 3 Enter Ctrl-D" without
the spaces, Ctrl-D being my tty's EOF, stty -a.

    $ ./stdin2.6
    1
    2
    3
    '1\n'
    '2\n'
    '3\n'

On the EOF the first iteration of sys.stdin returns and then so do the
others with the buffered lines.  The loop doesn't terminate, a second
Ctrl-D is required, giving.

    end
    $

Next,

    $ ./stdin3.1
    1
    '1\n'
    2
    '2\n'
    3
    '3\n'
    end
    $

perfect output.  Only one Ctrl-D required and better still each line is
returned as it's entered.

ltrace shows python2.6 uses fread(3).  I'm assuming it treats only a
zero return as EOF whereas whenever the return value is less than the
number of requested elements, EOF could have been reached;  feof(3) must
be called afterwards to decide.  Really, ferror(3) should also be called
to see if, as well as returning some elements, an error was detected.

It's this lack of feof() that means the second fread() is required to
trigger the flawed `only 0 return is EOF' logic.

Here's some C that shows stdio works fine if feof() and ferror() are
combined with fread().

    #include <stdio.h>

    int main(void)
    {
        unsigned char s[8192], *p;
        size_t n;

        while ((n = fread(s, 1, 8192, stdin))) {
            printf("%zd", n);
            p = s;
            while (n--)
                printf(" %02hhx", *p++);
            putchar('\n');

            if (feof(stdin)) {
                puts("end");
                break;
            }
            if (ferror(stdin)) {
                fputs("error", stderr);
                return 1;
            }
        }

        return 0;
    }
History
Date User Action Args
2012-01-28 18:31:20ralph.corderoysetrecipients: + ralph.corderoy, doko, ggenellina, draghuram, marhar, r_mosaic, benjamin.peterson, eric.araujo, nvetoshkin, BreamoreBoy, Finkregh
2012-01-28 18:31:19ralph.corderoysetmessageid: <1327775479.85.0.714378132553.issue1633941@psf.upfronthosting.co.za>
2012-01-28 18:31:19ralph.corderoylinkissue1633941 messages
2012-01-28 18:31:18ralph.corderoycreate