scanf Module

scanf.py: scanf-style input for Python.

Danny Yoo (dyoo@hkn.eecs.berkeley.edu)

The initial motivation for this module was based on a posting on Python-tutor:

I haven’t been able to find a nice module to do scanf-style input. Even the Library Reference recommends regular expressions as a substitute:

But there appears to have been activity about this on python-list:

Still, let’s see if we can get a close equivalent scanf() in place. At the least, it’ll be fun for me, and it might be useful for people who are still recovering from C. grin

Functions provided:

scanf(formatString) – formatted scanning across stdin

sscanf(sourceString, formatString) – formated scanning across strings

fscanf(sourceFile, formatString) – formated scanning across files

The behavior of this scanf() will be slightly different from that defined in C, because, in truth, I’m a little lazy, and am not quite sure if people will need all of scanf’s features in typical Python programming.

But let’s first show what conversions this scanf() will support. Format strings are of the following form:

% [*] [width] [format]

where [*] and [width] are optional, and [format] is mandatory. The optional flags modify the format.

  • suppresses variable capture.

width maximum character width.

We support the following scanf conversion formats (copied from K&R):

d decimal integer.

i integer. The integer may be in octal (leading zero) or
hexadecimal (leading 0x or 0X). ## fixme

o octal integer (with or without leading zero). ## fixme

x hexadecimal integer (with or without leading 0x or 0X) ## fixme

c characters. The next input characters (default 1) are
placed at the indicated spot. The normal skip over white space is suppressed; to read the next non-white space character, use %1s.

s character string (not quoted).

f floating-point number with optional sign and optional decimal point.

% literal %; no assignment is made.

Literal characters can appear in the scanf format string: they must match the same characters in the input.

There is no guarantee of what happens if calls to scanf are mixed with other input functions. See the BUGS section below for details on this.

If the input doesn’t conform to the format string, a FormatError is raised.

Example format strings:

“%d %d” Two decimal integers.

“%d.%d.%d.%d” Four decimal integers, separated by literal periods.
The periods won’t be captured.
“hello %s” Literally matches “hello” followed by any number of
spaces, followed by a captured word.

There’s also an interface for calling the internal function bscanf() that works on CharacterBuffer types, if in the future there is something that supports getc() and ungetc() natively. There’s also an undocumented compile() function that takes format strings and returns a function that can scan through CharacterBuffers. Ooops, I guess I just documented it. grin


BUGS and GOTCHAS:

One major problem that I’m running into is a lack of ungetc(); it would be nice if there were such a function in Python, but I can’t find it. I have to simulate it by using a CharacterBuffer object, but it’s not an ideal solution.

So at most, you may lose a single character to the internal buffers maintained by this module if you use scanf(). The other two *scanf() functions, thankfully, aren’t effected by this problem, since I can simulate ungetc() more accurately by using seek() in the other two cases.

If you really need to get that buffered character back, you can grab it through _STDIN.lastChar, though manually fiddling with this is not recommended.

So use scanf() with the following caveat: unlike C’s stdin(), this version scanf() can’t be interchanged with calls to other input functions without some kind of weird side effect. We keep a one-character buffer into stdin, so at most you might lose one character to the internal buffers.

fscanf() is only allowed to work on things that support both read(1) and seek(1, -1), since then I can reliably do a ungetch-like thing.

scanf(“%s”) can be dangerous in a hostile environment, since it’s very possible for something to pass in a huge string without spaces. So use an explicit width instead if you can help it.


LICENSE

Copyright (c) 2008, Danny yoo All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

scanf.scanf(formatString) → tuple[source]

Scans standard input for formats specified in the formatString. See module’s docs for list of supported format characters.

scanf.sscanf(inputString, formatString) → tuple[source]

Scans inputString for formats specified in the formatString. See module’s docs for list of supported format characters.

scanf.fscanf(inputFile, formatString) → tuple[source]

Scans inputFile for formats specified in the formatString. See module’s docs for list of supported format characters.

Previous topic

conf Module

Next topic

PyZenity Module

This Page