首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析文本文件函数

解析文本文件函数
EN

Code Review用户
提问于 2014-08-03 16:46:43
回答 2查看 2.7K关注 0票数 4

此方法获取我的工作计划的文本文件并对其进行分析。这是可行的,但有点俗套,我正在寻找反馈和建议。我第一次尝试使用文件解析器,第一次看Python (我涉足了Java/Android和JavaScript)。我希望在伪代码和注释之间能清楚地知道发生了什么。

伪码:

def read_body():f= open(' file ') tempList = [] d=自定义数据对象(),用于f: if行,而不是空行: if以马克龙开头:#表示文件中新的一天,为f:拆分行准备新的/空的数据对象如果行不是空行,如果行是工作日志,则在数据对象中记录它的另一个活动,如果支付值,同时记录它,elif以等号开头:#表示一天的结束,否则:清理f.close()

“全面守则”(起作用):

代码语言:javascript
复制
macron = '¯'
equalSign = '='
underscore = '_'

def read_body(path, month_year):
    '''Reads schedule detail text file and generates pairing data objects for each work day.
        path:   file to open 'monthYEAR.txt'
        date:   MonthYEAREMPNO (month, year, employee number)
                from file header
                '''
    f = open(path)
    tempList = []
    d = WorkDay()
    for line in f:
        tempList = line.rsplit()
        if len(tempList) > 0:
            if macron in tempList[0]:       #begin work day
                #prepare new data object
                d.clear()
                d.month_year(month_year)
                for line in f:
                    tempList = line.rsplit()
                    if len(tempList) > 0:
                        if isWorkingDay(tempList[0]):   #parse tempList[1] date block MM/dd/YYYY
                            d.activity_name(tempList[0])
                            d.date_of_month(tempList[1])
                            line = f.next()
                            tempList = line.rsplit()
                            d.hours_worked(tempList[1])
                            d.pay(tempList[3])
                            break
                        else:       #is other activity (sick, off, vacation, etc), log date/time/pay
                            d.activity_name(tempList[0])   #tempList[0] failed isWorkingDay(), so just print.  Human readable string
                            for line in f:
                                if underscore in line:
                                    break
                                elif 'Credit:' in line:
                                    d.pay(line[8:12])
                            break
            elif equalSign in tempList[0]:   #end work day
                #drop activity object in "write to db" queue
                add_to_db(d)
    else:
        '''end of file, clean up partial data objects.  necessary because schedule text file ends with a macron'''
        #discard d if empty, raise error if non-complete, write to db if complete
        pass
    f.close()
EN

回答 2

Code Review用户

发布于 2014-08-03 17:30:18

作为可读性的建议,我建议您替换

代码语言:javascript
复制
if len(tempList) > 0:

使用

代码语言:javascript
复制
if tempList:

当空列表解析为False时。

还建议在处理文件时使用"with语句“以避免错误。

代码语言:javascript
复制
with open('file') as f:
   ...

一旦该块退出,这将释放文件系统上的任何锁。

票数 4
EN

Code Review用户

发布于 2014-08-04 04:28:54

  • 这些常量(macronequalSignunderscore)被命名得有点无用。拥有const int TEN = 10是没有用的;使用反映常量的名称。(当您需要在新版本中更改常量时,这也有助于避免const int TEN = 11的类比情况.)更好的是,将常量放入谓词函数中,将所有检查封装在一个易于使用的包中。
  • 您的文件句柄上的嵌套循环可能有效,但它们令人费解。我建议使用外部while True循环和对f.next()的手动调用。
  • 您的代码非常嵌套。尝试将其拆分为多个函数。
  • 通常最好是提前返回(if not tempList: break)而不是嵌套(if tempList: ...)。
  • 您的内部循环可以改进,以便一次处理整个“记录”(开始日期,事情发生,结束一天),而不是每一行和笨拙地维护状态。(这实际上需要改变结构以删除循环,并明确定义处理序列;将代码移动到自己的函数中只是加分。)
  • 所有执行分支共有的一些代码(d.month_year(month_year)是一个点,d.activity_name(tempList[0])是另一个点)可以从分支结构中移出。
  • 如果一天没有在前一天结束,代码就会抛出前一天。你可能想改变这一点。
  • 您不太清楚马克龙开始新的一天是否有它自己的代码;您的代码的行为就好像它是这样做的(扔掉了剩下的一行),所以我就这么做了。
  • 你的终止字符(马克龙,等于,下划线)-你说他们必须在线的开头,但然后测试他们是否在线的任何地方!结合上述逻辑的飞跃,您可以简化这些测试,以检查字符是否是其行中唯一的字符。
  • 其他活动部分(用_终止)在记录结束时不会终止记录。我想在另一段结束和记录结束之间有任何东西是不允许的。

同时考虑到克里斯托夫·赫格曼的指针,您的修改代码:

代码语言:javascript
复制
def isStartWorkDay(line):
    return line == "¯\n"

def isEndWorkDay(line):
    return line == "=\n"

def isEndOtherActivitySection(line):
    return line == "_\n"

def processRecord(f, d):
    # This line should just start a record
    line = f.next()
    if line == '\n':
        return False
    # Start of record should be start of record
    if not isStartWorkDay(line):
        raise Exception("You missed the ¯ at the start of the day")

    # First line always starts with a day or a special identifier ("sick" etc.)
    lineList = f.next().rsplit()
    d.activity_name(lineList[0])
    if isWorkingDay(lineList[0]):
        # Line 1 is day of week, day of month, [boring]
        d.date_of_month(lineList[1])
        # Line 2 is [boring], hours worked, [boring], pay, [boring]
        lineList = f.next().rsplit()
        d.hours_worked(lineList[1])
        d.pay(lineList[3])
    else:
        # Something special happened; go through lines describing it
        # I know this is potentially confusing (as I said above), but it's the "least bad" way
        for line in f:
            if isEndOtherActivitySection(line):
                # That's it for this section
                break
            elseif "Credit:" in line:
                # It's a pay credit, we need to record it
                d.pay(line[8:12])
            else:
                pass # Move along, nothing to see here

    # All right, this record had better be ending now
    line = f.next()
    if isEndWorkDay(line):
        return True
    raise Exception("You missed the = at the end of the day")

def readBodyIntoDb(path, month_year):
    '''Reads schedule detail text file and generates pairing data objects for each work day.
       path:   file to open 'monthYEAR.txt'
       date:   MonthYEAREMPNO (month, year, employee number)
               from file header'''
    d = None # WorkDay object; required in outer scope
    with open(path) as f:
        try:
            while True:
              d = WorkDay()
              d.month_year(month_year)
              if processRecord(f, d): # d modified by side effect
                  dbWrite(d)
        except StopIteration:
          # EOF. I filled this pseudocode in for you
          if isEmptyRecord(d):
              pass # Nothing to see here
          elseif isCompleteRecord(d):
              dbWrite(d) # Someone left off the last `=` or something
          else:
              raise Exception("incomplete record")
    return True

(我的Python有点生疏,所以里面可能有潜在的语法或逻辑错误。)

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/58924

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档