没有等同于fscanf
或 Java 的Scanner
. 最简单的解决方案是要求用户使用换行符分隔输入而不是空格分隔输入,然后您可以逐行读取并将行转换为正确的类型。
如果您希望用户提供更结构化的输入,那么您可能应该为用户输入创建一个解析器。有一些不错的 python 解析库,例如pyparsing。还有一个scanf
模块,尽管最后一次更新是 2008 年。
如果您不想有外部依赖项,那么您可以使用正则表达式来匹配输入序列。当然,正则表达式需要处理字符串,但您可以轻松克服以块读取的限制。例如,这样的事情在大多数情况下应该可以正常工作:
import re
FORMATS_TYPES = {
'd': int,
'f': float,
's': str,
}
FORMATS_REGEXES = {
'd': re.compile(r'(?:\s|\b)*([+-]?\d+)(?:\s|\b)*'),
'f': re.compile(r'(?:\s|\b)*([+-]?\d+\.?\d*)(?:\s|\b)*'),
's': re.compile(r'\b(\w+)\b'),
}
FORMAT_FIELD_REGEX = re.compile(r'%(s|d|f)')
def scan_input(format_string, stream, max_size=float('+inf'), chunk_size=1024):
"""Scan an input stream and retrieve formatted input."""
chunk = ''
format_fields = format_string.split()[::-1]
while format_fields:
fields = FORMAT_FIELD_REGEX.findall(format_fields.pop())
if not chunk:
chunk = _get_chunk(stream, chunk_size)
for field in fields:
field_regex = FORMATS_REGEXES[field]
match = field_regex.search(chunk)
length_before = len(chunk)
while match is None or match.end() >= len(chunk):
chunk += _get_chunk(stream, chunk_size)
if not chunk or length_before == len(chunk):
if match is None:
raise ValueError('Missing fields.')
break
text = match.group(1)
yield FORMATS_TYPES[field](text)
chunk = chunk[match.end():]
def _get_chunk(stream, chunk_size):
try:
return stream.read(chunk_size)
except EOFError:
return ''
示例用法:
>>> s = StringIO('1234 Hello World -13.48 -678 12.45')
>>> for data in scan_input('%d %s %s %f %d %f', s): print repr(data)
...
1234
'Hello'
'World'
-13.48
-678
12.45
您可能必须扩展它并正确测试它,但它应该会给您一些想法。