Python即使存在并且位于正确的目录中也不会打开文件

时间:2018-01-09 20:18:33

标签: python file-io

我有一个Python脚本,用于打开数据文件,查找相关行,并将结果存储为元组列表。在脚本中有一个函数 ValuesFromFile(年,月,日,soft_address)接受字符串值年,月,日和整数 soft_address ,这将是发现在行。该函数在一个或多个范围内使用,以查看位于另一个目录中的每日文件。详细,功能,

def ValuesFromFile(year,month,day,soft_address):
    """Given the year, month, day, find all the lines that contain the soft address
       and call GetValues() on the line to get the associated values over the hour.

       The function builds the filename, checks if it exists, then goes line-by-line
       finding the lines with the soft address.

       Return a list of tuples [(datetime, value)]"""

    filename = '../../BEMS/' + str(year) + str(month).zfill(2) + '/' + 'gd' + str(year) + str(month).zfill(2) + str(day).zfill(2) + '.txt'
    data_list = []
    print filename
    try:
        FileObject = open(filename,'r')

        for line in FileObject:
            check_line = line.rsplit()
            hour_check = 0 # Check the hour in case we are missing an hour
            if (str(soft_address) in check_line):
                temp_list = GetValues(line)
                for tuple_value in temp_list:
                    date = "%s-%s-%s %s:%s"%(str(year),str(month),str(day),str(tuple_value[0]),str(tuple_value[1]))
                    data_list.append((datetime.strptime(date,"%Y-%m-%d %H:%M"),tuple_value[2]))
        FileObject.close()
    except:
        data_list = MissingDay(str(year),str(month),str(day))
        print "Couldn't find file"

    finally:
        FileObject.close()

在上面的函数中,我通过连接文件的位置../../BEMS/str(year)+str(month).zfill(2)+'/',然后连接文件的实际名称'gd' + str(year) + str(month).zfill(2) + str(day).zfill(2) + '.txt'来创建文件名字符串。如果找到该文件,我检查sting软地址是否在行中,然后调用另一个函数。如果找不到该文件,则会打印"Couldn't find file."

当我在2017-10-012017-10-15的时间范围内运行脚本时,会打印文件名,然后执行try-except-finally。如果找到并正确处理文件,则没有输出。如果找不到该文件,则执行except并打印print语句。结果:

Output from Python Script

所以奇怪的是脚本能够找到所有其他文件。该文件存在于目录中,该目录通过检查确认: File Exists。此外,我们可以看到所有用户都对上一个屏幕截图中的文件具有读取权限。我尝试在文件上做一个chmod只是为了看到,并没有像预期的那样有用。

为了增加奇怪性,当我尝试从交互式解释器中读取文件时,我能够打开并读取文件:

Read of file through interactive interpreter

最后,我将文件重命名为check.txt并将其放在与代码相同的目录中,注释掉文件名构建,并将其替换为filename = "check.txt",重新编写脚本,文件仍然没有'由脚本找到。所以这似乎是特定于该文件。

1 个答案:

答案 0 :(得分:1)

作为Kevin points out in the comments,您不应该使用假定发生特定错误的裸except块。给定the bug I pointed out in my comment(如果open失败,finally块会在尝试呼叫UnboundLocalError时引发FileObject.close(),除非您正在捕捉和抑制UnboundLocalError,肯定不发生的一件事是打开文件失败。更有可能的是,您的解析失败,并且由于您将所有异常视为相同,因此您报告无法解析为打开文件失败。

要解决此问题,请重新组织您的代码以避免错误报告错误(当您正在处理错误时,请避免close可能不存在的内容:

def ValuesFromFile(year,month,day,soft_address):
    """Given the year, month, day, find all the lines that contain the soft address
       and call GetValues() on the line to get the associated values over the hour.

       The function builds the filename, checks if it exists, then goes line-by-line
       finding the lines with the soft address.

       Return a list of tuples [(datetime, value)]"""

    # Simplify path construction just because
    filename = '../../BEMS/{y}{m:02d}/{y}{m:02d}{d:02d}.txt'.format(y=year, m=month, d=day)
    data_list = []    
    print filename
    try:
        FileObject = open(filename,'r')
    except EnvironmentError as e:
        print "Error opening file:", e
        return MissingDay(str(year),str(month),str(day))

    # No code should go here, as exceptions raised here don't benefit from with
    # statement guaranteed closure

    # with statement guarantees it's closed on block exit, whether or not exception occurs
    # Normally, you'd open it in the with statement too, but in this case,
    # you wanted to handle errors from open immediately, so we separate it a bit         
    with FileObject:
        for line in FileObject:
            check_line = line.rsplit()
            hour_check = 0 # Check the hour in case we are missing an hour
            if str(soft_address) in check_line:
                temp_list = GetValues(line)
                for tuple_value in temp_list:
                    date = "%s-%s-%s %s:%s"%(str(year),str(month),str(day),str(tuple_value[0]),str(tuple_value[1]))
                    data_list.append((datetime.strptime(date,"%Y-%m-%d %H:%M"),tuple_value[2]))

return data_list

这样你:

  1. 只捕获您想要捕获的错误(EnvironmentError,其中包括Py2上的IOErrorOSError,以及从3.3开始的别名OSError期待它(open电话)
  2. 收到包含更多详细信息的错误消息,而不是盲目声称它没有找到该文件
  3. 来自其余代码的所有其他异常都不会中断,因此您会得到一个完整的堆栈跟踪和错误消息,告诉您没有期望期待的错误情况出了什么问题