python 3:在for循环中使用文件tell()会产生错误

时间:2016-04-17 16:25:41

标签: file python-3.x

嗨我想在列表中保存包含“CREATE TABLE”的所有行的位置 a)有更好,更正确的方法吗? (我是python的新手) b)为什么告诉被用于迭代器?我认为它是一个读取方法(或等价物),因此只是告诉位置不应该损害文件迭代过程。

所以我有以下课程:

class SQLParser(object):
def __init__(self,filename):
    self.file = open(filename,'r')
    self.createTablePositions=[]
    self.insertIntoPositions=[]

def findCreateTable(self):
    for line in self.file:
        if line.find("CREATE TABLE") is 0:
            print(line)
            self.createTablePositions.append(self.file.tell())



sqlhandler = SQLParser("sql.sql")
sqlhandler.findCreateTable()
print(sqlhandler.createTablePositions)

产生以下错误:“Traceback(最近一次调用最后一次):   文件“C:/Users/user/PycharmProjects/sqlparser/sqlparser.py”,第18行,in     sqlhandler.findCreateTable()   在findCreateTable中的文件“C:/Users/user/PycharmProjects/sqlparser/sqlparser.py”,第12行     curPos = self.file.tell() OSError:通过next()调用“

告知位置被禁用

我搜索了网络和stackoverflow,但我找不到直接解决我的问题。 - 目前解决方案就像重写next()方法一样超出了我的知识,我怀疑这个练习的目标是什么。

请您的建议高度评价!

2 个答案:

答案 0 :(得分:0)

首先,你永远不会关闭文件,这不好。

错误的产生主要是由于tell()方法的内部行为。通过for line in file迭代文件,您不断调用内部操作next(),这会混淆tell()方法的工作方式。通常最好使用特定方法从文件中读取数据:readline()readlines()。除非您知道完全您正在做什么,否则迭代由OS(文件系统)控制的对象可能会由于访问方法(有时)或其他方式的冲突而导致错误。

同样file.tell()方法返回光标的位置而不是您所在的行。因此,如果您说您正在阅读包含20个字符的第一行,则在使用file.readline()后,方法file.tell()将返回22(字符数加上结束字符或其他字符)

而不是你在做什么,我建议以不同的方式思考它。

class SQLParser(object):
    """
    Parses a SQL file.
    """

    def __init__(self,filename):
        self.createTablePositions= self.findCreateTable(filename)
        self.insertIntoPositions=[]

    def findCreateTable(self, filename):
        temp = []
        with open(filename, 'r') as file:
            # with operator closes the file upon exit of block
            fileNum = 0
            for line in file.readlines():
                if "CREATE TABLE" in line:
                    print(line)
                    temp.append(fileNum)
                fileNum += 1
        return temp


sqlhandler = SQLParser("sql.sql")
print(sqlhandler.createTablePositions)

因此,现在,您将在初始化类对象时解析文件。

然后,您可以继续为insertIntoPosition的其他方法执行类似的操作。

答案 1 :(得分:0)

如果你的SQL文件过大,根据this answer有两种解决方法:

  1. 使用 file.readline() 而不是 next()
with open(path, mode) as file:
    while True:
        line = file.readline()
        if not line:
            break
        file.tell()
  1. 使用 offset += len(line) 而不是 file.tell()
offset = 0
with open(path, mode) as file:
    for line in file:
        offset += len(line)