【问题标题】:os.chdir() caused unexpected behaviour with python multithreadingos.chdir() 导致 python 多线程出现意外行为
【发布时间】:2019-03-05 13:21:47
【问题描述】:

我是 Python 多线程的新手。在我的代码中,我调用了一个函数,该函数使用 chdir() 更改其工作目录,如下所示。

import threading
import os
import shutil

def sayHello(dirName,userName):
    if not os.path.exists(dirName):
        os.makedirs(dirName)
    else:
        shutil.rmtree(dirName)
        os.makedirs(dirName)

    os.chdir(dirName)
    f = open("hello.txt","w")
    f.write("Hello %s\n" %userName)
    f.close()

thread1 = threading.Thread(target=sayHello,args=('hiDir1','Andrew'))
thread2 = threading.Thread(target=sayHello,args=('hiDir2','Michael'))

thread1.start()
thread2.start()

thread1.join()
thread2.join()

预期的行为是,

  1. thread1 : 创建“hiDir1”目录,在“hiDir1”中创建“hello.txt”,在“hello.txt”中打印“Hello Andrew”
  2. thread2 : 创建“hiDir2”目录,在“hiDir2”中创建“hello.txt”并在“hello.txt”中打印“Hello Michael”

当我第一次运行代码时,它运行没有错误。所有文件均已正确生成。但是“hiDir2”在“hiDir1”里面。

没有删除生成的文件,我第二次运行它。两个目录都在那里。但只有“hiDir2”有正确的文本文件,文件上印有正确的信息。 “hiDir1”没有文本文件。弹出以下错误。

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "threadingError.py", line 9, in sayHello
    shutil.rmtree(dirName)
  File "/usr/lib/python3.5/shutil.py", line 478, in rmtree
    onerror(os.rmdir, path, sys.exc_info())
  File "/usr/lib/python3.5/shutil.py", line 476, in rmtree
    os.rmdir(path)
FileNotFoundError: [Errno 2] No such file or directory: 'hiDir1'ode here

当我第三次运行它而不删除文件时,第二次运行反之亦然。两个目录都在那里。但只有“hiDir1”具有正确输出的文本文件。 'hiDir2' 是空的。有以下错误消息。

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "threadingError.py", line 12, in sayHello
    os.chdir(dirName)
FileNotFoundError: [Errno 2] No such file or directory: 'hiDir2'

当我重复运行此程序时,第二次和第三次发生恰好一个接一个。(怎么会发生这种情况?每次都应该给出相同的输出,不是吗?)

据我了解,问题出在“chdir()”上。所以我重新安排了代码以摆脱'chdir()',如下所示。

import threading
import os
import shutil

def sayHello(dirName,userName):
    if not os.path.exists(dirName):
        os.makedirs(dirName)
    else:
        shutil.rmtree(dirName)
        os.makedirs(dirName)

    filePath1 = dirName+'/hello.txt'
    print("filePath1: ", filePath1)
    # os.chdir(dirName)
    f = open(dirName+'/hello.txt',"w")
    f.write("Hello %s\n" %userName)
    f.close()

thread1 = threading.Thread(target=sayHello,args=('hiDir1','Andrew'))
thread2 = threading.Thread(target=sayHello,args=('hiDir2','Michael'))

thread1.start()
thread2.start()

thread1.join()
thread2.join()

然后,没有问题。代码按预期运行。在 python 多线程中使用 os.chdir() 有什么问题吗?这是python线程模块中的错误吗?

谢谢。

【问题讨论】:

  • 使用chdir,您可以更改进程的工作目录,而不仅仅是线程。
  • 欢迎来到线程世界,这里的事情不会按照您期望的顺序发生。
  • @Matthias 上面所说的——工作目录是每个进程的,而不是每个线程的状态。但总的来说,(ab)使用chdir 和工作目录语义会使代码更难推理,所以我建议将其重构为始终使用绝对路径。
  • 换句话说:不要使用 os.chdir()。
  • 感谢您的 cmets :)

标签: python python-3.x multithreading chdir


【解决方案1】:

这个怎么样:

import threading

from pathlib import Path


def say_hello(dir_name, username):
    """
    Creates dir_name (and its parents dirs) if not dir_name does not exist,
    then it creates a hello.txt file with the legent: 'Hello <username>'

    Examples:

    >>> say_hello('say_hello/slackmart', 'SLACKMART')
    say_hello/slackmart not found. Creating say_hello/slackmart
    Writing to say_hello/slackmart/hello.txt
    """
    path = Path(dir_name)
    if not path.exists():
        print(f'{dir_name} not found. Creating {dir_name}')
        path.mkdir(parents=True)
    else:
        # I wouldn't remove the dir_name path here as it could be dangerous
        print(f'Found {dir_name}')

    file_path = path / Path('hello.txt')  # Yes, you can join paths by using /
    print('Writing to', file_path)
    file_path.write_text(f'Hello {username}\n')


if __name__ == '__main__':
    andrew = threading.Thread(target=say_hello, args=('hiAndrewDir', 'Andrew'))
    michael = threading.Thread(target=say_hello, args=('hiMichaelDir', 'Michael'))

    andrew.start()
    michael.start()

    andrew.join()
    michael.join()

演示时间:

$ python3 sayhello.py

https://docs.python.org/3/library/pathlib.html

【讨论】:

  • 谢谢@slackmart。这也是解决我的问题的好方法。
  • 如果在代码中包含解释,这个答案会更好。仅代码答案要求读者将您的代码与原始代码逐行​​和逐个字符进行比较,以了解您所做的更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-09
  • 2022-10-18
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
相关资源
最近更新 更多