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 eryksun
Recipients Alexander Riccio, eric.smith, eryksun, paul.moore, steve.dower, tim.golden, zach.ware
Date 2015-10-13.21:31:50
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1444771910.57.0.063270926983.issue25386@psf.upfronthosting.co.za>
In-reply-to
Content
> It would be interesting to know under what circumstances these 
> functions can fail.

The CRT _put[w]ch and _get[w]ch[e] functions will fail when called in a process that doesn't have a console. (Except get[w]ch may succeed if it follows unget[w]ch.) This is the case when running under pythonw.exe if the process hasn't first attached to a console via AllocConsole() or AttachConsole(). It also applies to python.exe when run as a detached process (i.e. the creation flag DETACHED_PROCESS) or after having detached the console via FreeConsole(). 

Note that even though the docs for get[w]ch [1] and get[w]che [2] state that "[t]here is no error return", these functions actually do return an error value of [W]EOF. This has been the case since at least back to Windows NT. Maybe Steve Dower can shed light on why this is undocumented.

Here's an example, tested on 64-bit Windows 10 in Python 3.5. This example calls the console I/O functions using both msvcrt and ctypes. Since there's no attached console, an error is expected, except when calling ungetwch followed by getwch.

    import os
    import sys
    import subprocess

    cmds_msvcrt = [
        "import msvcrt; msvcrt.ungetwch('a'); msvcrt.getwch()",
        "import msvcrt; msvcrt.ungetwch('a'); msvcrt.ungetwch('a')",
        "import msvcrt; msvcrt.getwch()",
        "import msvcrt; msvcrt.putwch('a')",
    ]

    csetup = "import sys,ctypes; ucrt = ctypes.cdll.ucrtbase; "

    cmds_ctypes = [
        csetup + "ucrt._ungetwch(ord('a')); sys.exit(ucrt._getwch())",
        csetup + "ucrt._ungetwch(ord('a')); sys.exit(ucrt._ungetwch(ord('a')))",
        csetup + "sys.exit(ucrt._getwch())",
        csetup + "sys.exit(ucrt._putwch(ord('a')))",
    ]

    def test(cmds):
        pythonw = os.path.join(sys.prefix, 'pythonw.exe')
        return [subprocess.call([pythonw, '-c', cmd]) for cmd in cmds]
    
    
    >>> test(cmds_msvcrt)
    [0, 1, 0, 0]

    >>> test(cmds_ctypes)
    [97, 65535, 65535, 65535]

65535 is WEOF. 

[1]: https://msdn.microsoft.com/en-us/library/078sfkak
[2]: https://msdn.microsoft.com/en-us/library/kswce429
History
Date User Action Args
2015-10-13 21:31:50eryksunsetrecipients: + eryksun, paul.moore, eric.smith, tim.golden, zach.ware, steve.dower, Alexander Riccio
2015-10-13 21:31:50eryksunsetmessageid: <1444771910.57.0.063270926983.issue25386@psf.upfronthosting.co.za>
2015-10-13 21:31:50eryksunlinkissue25386 messages
2015-10-13 21:31:50eryksuncreate