os.chdir () вызвал неожиданное поведение с многопоточностью Python - PullRequest
1 голос
/ 05 марта 2019

Я новичок в многопоточности в 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",создайте «hello.txt» внутри «hiDir1» и напечатайте «Hello Andrew» в «hello.txt»
  2. thread2: создайте каталог «hiDir2», создайте «hello.txt» внутри «hiDir2» и напечатайте «Hello»Майкл "in" hello.txt "

Когда я запускал код в первый раз, он работал без ошибок.Все файлы были сгенерированы правильно.Но «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'

Когда я запускал это несколько раз, 2-е и 3-е происшествия происходили ровно один за другим (как это может произойти? Это должно давать одинаковый результат каждый раз, не так ли?)

Как я понял, проблема в '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()

Тогда проблем не было.Код работает как ожидалось.Что-то не так с os.chdir () при использовании в многопоточности Python?Это ошибка в модуле потоков Python?

Спасибо.

1 Ответ

0 голосов
/ 05 марта 2019

Как насчет этого:

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

...