单线程中的os.makedir争用条件?如何确保在继续之前创建目录

2024-05-14 23:36:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我在flask应用程序中有非常奇怪的os.makedir行为

我有一个用于上传图像的API端点。应根据条件将每个图像分组到目录中。如果目录不存在,则应创建该目录

最初,我的应用程序中有以下代码:

    # create needed dir if doesn't exist
    if not os.path.isdir(os.path.dirname(abs_path)):
        os.mkdir(os.path.dirname(abs_path))

    # create a file and save it into a needed place
    with open(abs_path, 'wb') as f:
        shutil.copyfileobj(fp, f)
        f.flush()

在90%的情况下,它非常有效。但当请求中有两个文件时,它们应该放在同一个目录中,而目录尚未创建,我得到了以下信息:

flask_1  |   File "/app/storage.py", line 101, in save_file
flask_1  |     os.mkdir(os.path.dirname(abs_path))
flask_1  | FileExistsError: [Errno 17] File exists: '/static/df273d04909e71beb8b63b4d1b1c0a969ee6fc15'

在flask调试模式下,使用1个线程,可以在本地复制,100%成功。这似乎是某种Linux/docker或某种缓存竞争条件

然后我简单地将代码更改为:

if not os.path.isdir(os.path.dirname(abs_path)):
    try:
        os.mkdir(os.path.dirname(abs_path))
    except FileExistsError:
        # Another thread was already created the directory when
        # several simultaneous requests has come
        if os.path.isdir(os.path.dirname(abs_path)):
            pass
        else:
            raise

    # create a file and save it into a needed place
    with open(abs_path, 'wb') as f:
        shutil.copyfileobj(fp, f)
        f.flush()

问题已经解决了

但我担心在生产中使用此代码,因为很奇怪,相同的检查会产生不同的结果

如何确保在继续第一次请求处理之前确实创建了目录

p.S.文件已就位,第二个代码段和两个文件均已就位。第一个文件只包含目录中的第一个文件,第二个文件出错

例如,对于第一个代码片段,Flask认为一切正常并继续


Tags: 文件path代码目录flaskifossave

热门问题