凉城旧巷
Python从入门到自闭,Java从自闭到放弃,数据库从删库到跑路,Linux从rm -rf到完犊子!!!

Python多线程的坑——切换工作目录导致错误

复现:

import os
import time
from concurrent.futures import ThreadPoolExecutor


def thread_func(a):
    origin = os.getcwd()
    print(str(a) * 5 + '>>:', origin)
    if a == 1:
        os.chdir('/data/users/fhu/PycharmProjects/Buildflow/tools')
        print('111: %s' % os.getcwd())
    elif a == 2:
        print('222: %s' % os.getcwd())
    print(a)
    os.chdir(origin)


def main():
    pool = ThreadPoolExecutor(20)
    for i in range(0, 2):
        a = i + 1
        pool.submit(thread_func, a)

    pool.shutdown(wait=True)


if __name__ == '__main__':
    main()
  • 多次运行,可能出现了不相同的结果,由于两个线程运行的速度是不确定的,所以会出现不同的结果。
  • 线程1的结果使用没变,但是,线程2的打印结果是变化的

 

原因:

当前工作环境,在线程之间是共享的,所以,在多线程中,如果其中一个线程通过os.chdir()修改了工作目录,那么会出现一定概率,导致其它线程的工作目录也随之改变。

如果线程A切换到新路径工作时,由于工作时间较长,并没有切回到原始路径。而此时,线程B也在工作,他的路径被线程A切换了,导致在错误的路径中工作

 

验证方法:

该方法验证多线程中使用os.chdir()切换工作目录的方式,会影响其它线程的工作目录

import os
import time
from concurrent.futures import ThreadPoolExecutor


def thread_func(a):
    origin = os.getcwd()
    print(str(a) * 5 + '>>:', origin)
    if a == 1:
        os.chdir('/data/users/fhu/PycharmProjects/Buildflow/tools')
        time.sleep(5)
        print('111: %s' % os.getcwd())
    elif a == 2:
        time.sleep(2)
        print('222: %s' % os.getcwd())
    print(a)
    os.chdir(origin)


def main():
    pool = ThreadPoolExecutor(20)
    for i in range(0, 2):
        a = i + 1
        pool.submit(thread_func, a)

    pool.shutdown(wait=True)


if __name__ == '__main__':
    main()
  • 此时,线程2的工作目录永远是因为线程1切换的新目录,不是自己的原始目录。

 

解决:

在多线程中尽量不要使用os.chdir()来进行目录切换,可以用绝对路劲来进行操作。

例如:

  • os路径操作时,使用绝对路径操作,而不是先切换目录,再使用相对路径操作
  • subprocess执行命令时,使用subprocess的cwd参数,来指定工作路径
  • 采用多进程的方式,因为进程间是隔离的,互不影响,但是多进程的资源消耗相对多
posted on 2023-03-15 17:04  凉城旧巷  阅读(412)  评论(0编辑  收藏  举报