【问题标题】:PermissionError: [Errno 13] Permission denied (after multiple successful writting attemps in the file)PermissionError: [Errno 13] Permission denied (在文件中多次成功写入后)
【发布时间】:2017-10-16 21:03:43
【问题描述】:

我编写了一个查询 mongo 数据库并将结果写入文件的代码。 我的代码创建了文件并开始成功在其中写入。但是经过多次迭代(不确定迭代次数是否固定)我得到了 PermissionError

我已经搜索过它,但我只找到了第一次尝试出错的人的答案,因为他们没有权限。我会准确地说,在执行期间我没有在我的电脑上做任何事情,所以我真的不明白它是怎么发生的。

以下是部分代码:

def query(self, query_date_part, query_actKey_part, filepath):
    empty = True
    print("0.0 %")
    for i in range(len(query_date_part)):
        query = {"dt": query_date_part[i], "actKey": query_actKey_part}
        cursor = self.collection.find(query)
        while cursor.alive:
            try:
                if empty:
                    with open(filepath, 'w') as fp:
                        json.dump(cursor.next(), fp, default=json_util.default)
                        empty = False
                else:
                    append_to_json(filepath, cursor.next())
            except StopIteration:
                print("Stop Iteration")
        print(str(round(float(i+1) / len(query_date_part) * 100, ndigits=2)) + " %")
    return 0
def append_to_json(filepath, data):
    """
    Append data in JSON format to the end of a JSON file.
    NOTE: Assumes file contains a JSON object (like a Python dict) ending in '}'.
    :param filepath: path to file
    :param data: dict to append
    """
    # construct JSON fragment as new file ending
    new_ending = ", " + json.dumps(data, default=json_util.default)[1:-1] + "}\n"
    # edit the file in situ - first open it in read/write mode
    with open(filepath, 'r+') as f:
        f.seek(0, 2)        # move to end of file
        index = f.tell()    # find index of last byte
        # walking back from the end of file, find the index
        # of the original JSON's closing '}'
        while not f.read().startswith('}'):
            index -= 1
            if index == 0:
                raise ValueError("can't find JSON object in {!r}".format(filepath))
            f.seek(index)
        # starting at the original ending } position, write out
        # the new ending
        f.seek(index)
        f.write(new_ending)`

部分输出:

6.75 %
Stop Iteration
6.76 %
Traceback (most recent call last):
    File "C:/Users/username/PycharmProjects/mongodbtk/mquerytk.py", line 237, in <module>
        mdbc.query(split_date(2017,5,6,1,0,2017,5,16,10,0,step=2), {"$in": ["aFeature"]}, 'test.json')
    File "C:/Users/username/PycharmProjects/mongodbtk/mquerytk.py", line 141, in query
        append_to_json(filepath, cursor.next())
    File "C:/Users/username/PycharmProjects/mongodbtk/mquerytk.py", line 212, in append_to_json
        with open(filepath, 'r+') as f:
PermissionError: [Errno 13] Permission denied: 'test.json'
Process finished with exit code 1

注意:在执行过程中文件的大小会增加。当它崩溃时大约是 300 个月,我的硬盘驱动器上还有很多空间,但文件的大小可能是个问题?

配置:我使用的是 Windows 7、Python 3.6,我的 IDE 是 PyCharm Community Edition 2016.3.2

【问题讨论】:

  • 使用“with open...”应该关闭文件。有可能不是吗?
  • 您确定append_to_json 正在执行多次吗?似乎是在else 条件下
  • @itzMEonTV if else 只是在第一次迭代时重新创建文件然后 append_to_json 被执行多次(我确信因为文件的大小在执行过程中会增加)
  • 在 Windows 中,默认情况下,当一个进程打开一个文件时,它会以独占方式打开它——没有其他人可以打开该文件。所以只有一个给定文件的打开。您看到的症状表明锁定尚未被关闭的文件清除。因此,我会查看您的代码以查找可能导致该问题的原因。
  • 更改设计。在query 中,不是为光标中的每个元素打开和关闭文件,而是先打开文件,然后从光标开始添加元素。或者,如果内存允许,在内存中构建整个 json 并在最后写入文件。

标签: python python-3.x permissions


【解决方案1】:

这似乎是一个竞争条件。创建一个辅助函数,它与引发竞争条件的函数执行相同的任务,这对我来说很有效。 例如,如果代码块或函数 A() 正在创建竞争条件,那么我们可以通过再次调用另一个帮助函数 A_helper() 来处理这个异常,它也做同样的事情。 一个python代码示例:

try:
   A()
except PermissionError:
   # Do something
else:
   A_helper()

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,在对其进行测试后,似乎在尝试“经常”写入同一文件时可能存在一些“错误”,每秒钟多次。我将提供一个非常小的代码 sn-p 供您测试:

    import csv
    
    text = "dfkjghdfkljghflkjghjkdfdfgsktjgrhsleiuthsl uirghuircbl iawehcg uygbc sgygerh"
    FIELD_NAMES = ['asd', 'qwe']
    
    
    with open('test.txt', 'w', newline='') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=FIELD_NAMES)
        writer.writeheader()
    
    max = 10000
    i = 0
    
    while i <= max:
        print(str(i))
        with open('test.txt', 'a', newline='') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=FIELD_NAMES)
            rowData = {'asd': text, 'qwe': text}
            writer.writerow(rowData)
        i += 1
    

    我认为代码很容易解释。我非常随机地收到错误,有时它发生在第 75 次迭代之后,有时甚至可以达到 ~750,但看起来代码无法达到限制。因此,我建议您尝试多次写入更多数据,而不是经常写入少量数据。希望对你有帮助。

    【讨论】:

    • 是的,这正是发生的情况,我通过每次写入更多数据以减少打开和关闭文件的频率来解决问题。但是,我仍然没有找到 100% 确定的解释为什么会发生这种情况:/
    【解决方案3】:

    试试这个

    except StopIteration:
        if not fp.closed: fp.close()
        print("Stop Iteration")
    

    【讨论】:

    • 我不确定我是否理解你想用这段代码做什么。我发布了很多没有很好评论的代码,所以也许这不是你的意思?
    • 不,它不起作用。顺便说一句,我真的不明白你为什么在除了 StopIteration 中写这个。因为这种例外不会经常发生,即使它调用 StopIteration 也与我的问题无关。所以我可能不明白你的想法,或者你对我不正确的代码感到困惑
    • 好的。这是在停止迭代之后发生的吗?从错误日志来看是这样的。是不是一直都一样?此外,我正在尝试仅调试您的代码。会出现特定用户的最大打开文件限制或close 无法按预期工作的情况。
    • 不,它与停止迭代无关,我应该发布更多日志,不,它并不总是相同的确切时间。是的,我的代码做了数千次打开/关闭,所以我目前正在遵循 valentin 的建议来减少文件打开/关闭的频率和数量
    • 尝试保留 1000 个(您可以更改)对象并进行写入。因此,除了在每个循环中打开之外,它无论如何都会表现良好。
    【解决方案4】:

    您的文件位于程序无法访问的位置。尝试将其移动到其他目录。或者可能是您输入了错误的文件路径。我希望这对你有用!

    【讨论】:

    • 该文件是由该程序创建的,并且在引发此错误之前它已经在其中写入了很多次
    • 电脑中是否有不允许python访问过大文件的功能?
    猜你喜欢
    • 2017-02-12
    • 1970-01-01
    • 2019-07-31
    • 2016-08-17
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多