Как исправить ошибку с missing 1 required positional argument: 'self'?
Я написал код для поиска обалютно одинаковых фото, сейчас пытаюсь его оптимизировать, решил сделать через класс, чтоб удобней было работать с multiprocessing и в следствии чего вылезла ошибка: TypeError: calculating() missing 1 required positional argument: 'self'
from PIL import Image
import glob
import os
from datetime import datetime
from numpy import array, delete, append
# from numpy import delete, append
from multiprocessing import Process, set_start_method
filename_list = glob.glob('C:/Users/administrator/Desktop/)/*')
images = filename_list
used_images = []
bad_image = []
true_bad_images = []
good_image = []
pic_image = []
pic_image1 = []
images = array(images)
used_images = array(used_images)
bad_image = array(bad_image)
true_bad_images = array(true_bad_images)
good_image = array(good_image)
pic_image = array(pic_image)
pic_image1 = array(pic_image1)
class lets_do_this:
def __init__(self):
self.image1 = Image.open(images[self.j])
self.image = Image.open(images[self.i])
self.width1 = self.image1.size[0]
self.width = self.image.size[0]
self.height1 = self.image1.size[1]
self.height = self.image.size[1]
self.pix1 = self.image1.load()
self.pix = self.image.load()
def calculating(self):
for i in range(len(images)):
self.i = i
# print(f'{i}')
for j in range(len(images)):
self.j = j
# print(f'{i}.{j}')
if i != j:
if self.width == self.width1 and self.height == self.height1:
set_start_method('spawn')
p1 = Process(target=lets_do_this.first_step)
p1.start()
p1.join()
else:
if len(good_image) != 0:
for m in range(len(good_image)):
if good_image[m] != images[i] and m == len(good_image) - 1:
append(good_image, images[i])
else:
append(good_image, images[i])
# pic_image.clear()
# pic_image1.clear()
delete(pic_image, [m for m in range(len(pic_image))], axis=None)
delete(pic_image1, [m for m in range(len(pic_image1))], axis=None)
append(used_images, images[i])
print(good_image, bad_image)
print(datetime.now() - start)
break
# pic_image.clear()
# pic_image1.clear()
delete(pic_image, [m for m in range(len(pic_image))], axis=None)
delete(pic_image1, [m for m in range(len(pic_image1))], axis=None)
print(f'--------------------')
p1 = Process()
p1.start()
p1.join()
def first_step(self):
i = self.i
for k in range(self.width):
for l in range(self.height):
append(pic_image, self.pix[k, l])
for k1 in range(self.width1):
for l1 in range(self.height1):
append(pic_image1, self.pix1[k1, l1])
if pic_image == pic_image1:
p1 = Process(target=lets_do_this.second_step)
p1.start()
p1.join()
else:
if len(good_image) != 0:
for m in range(len(good_image)):
if good_image[m] != images[i] and m == len(good_image) - 1:
append(good_image, images[i])
else:
append(good_image, images[i])
def second_step(self):
i = self.i
if len(bad_image) != 0:
if len(used_images) != 0:
append(bad_image, images[i])
else:
append(bad_image, images[i])
else:
if len(used_images) != 0:
append(bad_image, images[i])
else:
append(bad_image, images[i])
if len(good_image) != 0:
for m in range(len(good_image)):
if good_image[m] != images[i] and m == len(good_image) - 1:
append(good_image, images[i])
else:
append(good_image, images[i])
def third_step():
if bad_image is not None:
for i in range(len(bad_image)):
for j in range(len(bad_image)):
if i != j:
image = Image.open(images[i])
image1 = Image.open(images[j])
width = image.size[0]
width1 = image1.size[0]
height = image.size[1]
height1 = image1.size[1]
if width == width1 and height == height1:
if len(true_bad_images) != 0:
for a in range(len(true_bad_images)):
if len(used_images) != 0:
for b in range(len(used_images)):
if true_bad_images[a] == used_images[b]:
pass
elif b == len(used_images) and a == len(true_bad_images):
append(true_bad_images, bad_image[i])
append(used_images, bad_image[j])
else:
if true_bad_images[a] == bad_image[i]:
pass
elif a == len(true_bad_images):
append(true_bad_images, bad_image[i])
append(used_images, bad_image[j])
else:
append(true_bad_images, bad_image[i])
if len(used_images) != 0:
for a in range(len(used_images)):
if used_images[a] != bad_image[j]:
append(used_images, bad_image[j])
else:
append(used_images, bad_image[j])
end()
start = datetime.now()
if __name__ == '__main__':
set_start_method('spawn')
p_start = Process(target=lets_do_this.calculating)
p_start.start()
p_start.join()
def end():
true_good_images = good_image[:]
true_good_images = array(true_good_images)
for i in range(len(good_image)):
for j in range(len(true_bad_images)):
if good_image[i] == true_bad_images[j]:
delete(true_good_images, j)
for i in range(len(true_bad_images)):
if len(true_bad_images) != 0:
if os.path.isfile(true_bad_images[i]):
os.remove(true_bad_images[i])
print(datetime.now() - start)
print(f'\nbad image: {true_bad_images}\n good image: {good_image}\n true good images: {true_good_images}')
print(f'success :)')
это лишь часть кода, но пока только тут и ошибка, если надо могу выслать весь код), помогите пожалуйста
Ответы (1 шт):
Поскольку first_step и second_step - это методы экземпляра класса, то попробуйте вызывать их от экземпляра класса, а не просто от класса:
p1 = Process(target=self.first_step)
...
p1 = Process(target=self.second_step)
...
p_start = Process(target=lets_do_this().calculating)
Если так не получится, можно попробовать в явном виде вызывать через lambda:
p1 = Process(target=lambda: self.first_step())
...
p1 = Process(target=lambda: self.second_step())
...
p_start = Process(target=lambda: lets_do_this().calculating())
Но вообще многопоточность не такая уж простая штука. Процессы работают с копией данных того процесса, из которого вы их вызываете. Поэтому всё, что вы меняете в этих дополнительных процессах, там же и остаётся, в основном процессе данные остаются прежние, не зависимые от изменений в порождённых процессах.
Так что от ошибки вы может быть и избавитесь, а вот от проблем в архитектуре программы - скорее всего нет. Придётся её капитально переосмысливать.
Если хотите правильно работать с процессами, то подумайте, что в них нужно передавать и что получать из них обратно. Передачу нужно будет сделать в явном виде, а не надеяться на то, что всё и так само передастся. Если ничего не делать, то туда передастся слишком много, а обратно не передастся ничего. Поэтому передаваемые данные нужно минимизировать, иначе выигрыша от многопроцессности не будет, весь выигрыш съест сериализация и передача данных сначала в процесс, а потом обратно. И да, нужно будет в явном виде передать данные в процесс и получить их в явном виде обратно.
Так что скорее всего проще использовать multiprocessing.Pool, в него проще передавать данные и получать их обратно после обработки.