2016-04-14 3 views
1

У меня есть функция, myfunc, которая вызывается в параллельной обработке. Когда я делаю несколько процессов совместно одной и той же папкой назначения, все они вызывают myfunc параллельно и проверяют наличие папки назначения. Если он уже существует, проблем нет. Однако, если папка не существовала до запуска сценария, тогда первый процесс войдет в блок if и создаст папку. С другой стороны, будет еще один процесс, который будет вводить то же самое, если блок «почти» в одно и то же время, обнаружит, что папка не существует, и попытается создать ее, в то время как первый процесс фактически создает ее или уже сделал это. Поэтому в какой-то момент будет OSError, говорящий, что папка уже существует.правильная проверка существования файла при многопроцессорной обработке

Есть ли чистый способ справиться с этой проблемой при многопроцессорной обработке? Я думаю о том, чтобы заботиться о папке назначения из функции myfunc, прежде чем запускать мои процессы. Было бы неплохо найти решение, использующее многопроцессорность, ради знания.

import os, sys 

def myfunc(file_names, destination=None, file_permission=None, verbose=False): 
    absPath = os.path.abspath(file_names[0]) 
    baseName = os.path.basename(absPath) 
    dirName = os.path.dirname(absPath) 


    destination_folder = "/default/destination" if destination is None \ 
     else os.path.abspath(destination) 

    if not os.path.isdir(destination_folder): 
     os.mkdir(destination_folder) 
     os.chmod(destination_folder, file_permission) 
     if verbose: 
      print "Created directory", destination_folder 
+0

Хорошо, поймайте исключение? – BlackBear

ответ

0

Использование Lock из threading модуля для решения проблем параллелизма:

import os, sys 
from threading import Lock 

def myfunc(lock, ...): 
    ... do stuff as usual ... 

    with lock: 
     destination_folder = "/default/destination" if destination is None \ 
      else os.path.abspath(destination) 

    ... do everything else as usual ... 

if __name__ == "__main__": 
    my_lock = Lock() 
    myfunc(my_lock, ...) 
+1

И если используется «многопроцессорность» (в соответствии с заголовком), то эквивалент «multiprocessing.Lock». –

1

Проверка существования файла/папки и принятия решения на основе результата в корне неверно, в большинстве случаев, потому что даже если вы не многопроцессорны, вы не знаете, что еще работает на компьютере. Также трудно гарантировать, что кто-то еще не будет запускать несколько копий вашего процесса, даже если вы этого не предполагали.

Самый надежный метод - всегда пытаться создать папку и молча игнорировать ошибку «но это уже существует». (Не игнорируйте другие ошибки, такие как «но у вас нет этого разрешения»!) Это все равно было бы лучшим способом сделать что-либо, даже если вы сделали одну проверку перед началом многопроцессорности.

+0

Считаете ли вы, что нужно использовать комбинацию исключения и блокировки? На самом деле я не знаю, какой ответ наиболее адекватен между вашими и th3an0maly. – kaligne

+0

Чтобы быть надежным, вы должны поймать исключение. В общем случае, даже если ваши блокировки идеальны, другая программа может неожиданно изменять файлы или папки из-под вас. Как только вы это сделаете, вы можете оценить, добавляет ли также использование блокировок или условных выражений. Там определенно есть места, где они будут полезны, но я не думаю, что это одно из этих мест. Как только вы поймаете исключение, блокировка добавляет дополнительную сложность этому решению без дополнительной безопасности. – GrandOpener