沒有等效的fscanf
或Java的Scanner
。最簡單的解決方案是要求用戶使用換行分隔輸入而不是空格分隔輸入,然後可以逐行讀取並將行轉換爲正確的類型。
如果您希望用戶提供更多結構化的輸入,那麼您可能應該爲用戶輸入創建解析器。 python有一些很好的解析庫,例如pyparsing。即使最後一次更新是2008年,也有一個scanf
模塊。
如果您不想有外部依賴關係,那麼您可以使用正則表達式來匹配輸入序列。當然,正則表達式需要使用字符串,但是您可以輕鬆地克服塊中讀取的限制。例如這樣的事情應該工作以及大部分的時間:
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
你可能會不得不延長這一點,並進行適當的測試,但它應該給你一些想法。
如果輸入非常髒/任意,我傾向於使用're'模塊;如果輸入是結構化的,我更喜歡像simpleparse這樣的解析器庫(EBNL比正則表達式更容易維護)。 – 2013-02-16 01:25:57
如果您確實有一個用例,那麼更新您的問題而不是進行通用查詢可能會更有成效。 – 2013-02-16 01:34:12
有關其他建議,請參見http://stackoverflow.com/questions/2175080/sscanf-in-python。 – 2013-02-16 01:55:37