有限状态机问题:来自文本文件的所有读取输入都被置于错误状态

时间:2016-04-20 18:53:12

标签: python text-files state-machine

我们的类项目已经走到了尽头,我们有三个文件,两个是我们的转换和状态机程序,另一个是我们的语句文本文件。一切似乎都有效,除非我们尝试输入文本文件时,它总是将其归类为error_state。但是,如果我们将输入读入转换程序,它就能正常工作。

这是我们的结果:

Greg is beautiful

('reached the end state that is a ', 'error_state')
Greg is ugly

('reached the end state that is a ', 'error_state')
Greg is O.K.

('reached the end state that is a ', 'error_state')

我们也尝试将其作为一个列表阅读并将其拆分。

这是我们的代码:

Statemachine.py

class StateMachine:
    def __init__(self):
        self.handlers = {}
        self.startState = None
        self.endStates = []

    def add_state(self, name, handler, end_state=0):
        name = name.upper()
        self.handlers[name] = handler
        if end_state:
            self.endStates.append(name)

    def set_start(self, name):
        self.startState = name.upper()

    def run(self, cargo):
        try:
            handler = self.handlers[self.startState]
        except:
            raise InitializationError("must call .set_start() before .run()")
        if not self.endStates:
            raise  InitializationError("at least one state must be an end_state")

        while True:
            (newState, cargo) = handler(cargo)
            if newState.upper() in self.endStates:
                print("reached the end state that is a ", newState)
                break 
            else:
                handler = self.handlers[newState.upper()]   

Transitions.py

from Statemachine import StateMachine

positive_adjectives = ["great","fun", "handsome", "beautiful"]
negative_adjectives = ["boring", "difficult", "ugly", "goofy"]

def start_transitions(txt):
    splitted_txt = txt.split(None,1)
    word, txt = splitted_txt if len(splitted_txt) > 1 else (txt,"")
    if word == "Greg":
        newState = "Greg_state"
    else:
        newState = "error_state"
    return (newState, txt)

def is_state_transitions(txt):
    splitted_txt = txt.split(None,1)
    word, txt = splitted_txt if len(splitted_txt) > 1 else (txt,"")
    if word == "is":
        newState = "is_state"
    else:
        newState = "error_state"
    return (newState, txt)

def not_state_transitions(txt):
    splitted_txt = txt.split(None,1)
    word, txt = splitted_txt if len(splitted_txt) > 1 else (txt,"")
    if word == "not":
        newState = "not_state"
    elif word in positive_adjectives:
        newState = "positive_state"
    elif word in negative_adjectives:
        newState = "negative_state"
    else:
        newState = "error_state"
    return (newState, txt)

def adjective_state_transitions(txt):
    splitted_txt = txt.split(None,1)
    word, txt = splitted_txt if len(splitted_txt) > 1 else (txt,"")
    if word in positive_adjectives:
        newState = "negative_state"
    elif word in negative_adjectives:
        newState = "positive_state"
    else:
        newState = "error_state"
    return (newState, txt)

def neg_state(txt):
    print("Not nice :(")
    return ("negative_state", "")

if __name__== "__main__":
    m = StateMachine()
    m.add_state("Start", start_transitions)
    m.add_state("Greg_state", is_state_transitions)
    m.add_state("is_state", is_state_transitions)
    m.add_state("not_state", not_state_transitions)
    m.add_state("negative_state", None, end_state=1)
    m.add_state("positive_state", None, end_state=1)
    m.add_state("error_state", None, end_state=1)
    m.set_start("Start")

    with open('states.txt', 'r') as f_input:
        statement1 = f_input.readline()
        statement2 = f_input.readline()
        statement3 = f_input.readline()
        print (statement1)
        m.run (statement1)
        print (statement2)
        m.run (statement2)
        print (statement3)
        m.run (statement3) 
        f_input.close()

states.txt

Greg is beautiful

Greg is ugly

Greg is O.K.

- 谢谢你!

1 个答案:

答案 0 :(得分:1)

您的代码无效的原因是您没有从states.txt中的每一行删除换行符。

换句话说,您的输入文本实际上看起来像这样(显示换行符):

Greg is beautiful\n
\n
Greg is ugly\n
\n
Greg is O.K.\n

(您可以通过将文件打开为f_input并在解释器中调用f_input.read()来验证这是Python看到的方式。)

states.txt阅读时,f_input.readline()执行(仅针对第一行)Greg is beautiful\n。您的功能将其拆分为['Greg', 'is', 'beautiful\n']

显然,额外的换行符将一切都抛弃了。 beautiful\n被识别为错误,所有内容都被归类为错误状态。这发生在所有的函数中。

解决方案

使用.strip()删除尾随换行符。在所有您的函数中,将txt替换为txt.strip(),然后再调用其上的split()函数。

e.g。

def start_transitions(txt):
    splitted_txt = txt.strip().split(None,1)
    ...

此外,我强烈建议删除所有输入行之间的额外空行。这将使您的生活更加轻松,特别是因为您可能无意中将空白行中的读数分配为您的陈述。

其他提示

此代码不是生产质量。您在所有函数中都有很多重复的代码(特别是对于分割输入文本),您可以使用Python's ternary expressions使其更简洁。

一旦您确信代码正常运行,我强烈建议您在CodeReview上询问如何改进此问题 - 它将使您和该计划受益匪浅。