Problem z pętlą for

0

Witam, mam problem z pętlą wykonuje się albo 2 razy albo o 1 raz za mało.
Rozwinę nieco działanie programu:

  1. Pobiera dane z links json i tworzy dla nich checkboxy.
  2. Po wybraniu checkboxow, zaznaczone dodaje do listy to_download
  3. Pobiera pliki z listy i odpakowuje

Chodzi o plik main.py (prawdopodobnie linie 157-271)
kodzik: https://github.com/Tomeczekqq/GarrysModContentAssistant

0

Zainteresuj się takim narzędziem jak debugger. Na pewno Ci pomoże.

0
 def init_download(self):
        '''
        Gets checkboxes state and adds it to query.
        Starts threading
        '''
        for choice in self.choices:
            if (choice.enabled.get()) and ((choice.tag in to_download) == False):
                to_download.append(choice)
            elif (choice.enabled.get() == False) and (choice.tag in to_download):
                to_download.remove(choice)
        self.thread = threading.Thread(target=self.queue)
        self.thread.daemon = True
        self.thread.start()

    def queue(self):
        '''
        -Setups ui disable checkboxes and place downloading widgets
        -Starts downloading from queue
        '''
        self.label_status['text'] = "Preparing queue"
        if to_download == []:
            self.label_path["text"] = "You need to select item to download"
            return False
        self.button_start.destroy()
        self.label_path.destroy()
        self.progressbar.place(x=30, y=525, width=740, height=10)
        self.label_eta.place(x=26, y=540)
        self.label_speed.place(x=690, y=540, width=100)
        self.label_status.place(x=30, y=500, width=740, height=20)
        self.label_status["text"] = "Preparing queue... | {0} items in queue)".format(
            len(to_download)
        )
        self.disable_checkboxes()
        for con in to_download:
            self.start_download(con)

    def start_download(self, content):
        '''
        Starts downloading and update widgets (eta, speed and status)
        '''
        if "mediafire" in content.url:
            content.url = tools.scrap_mediafire(content.url)
        downloader = SmartDL(content.url, gmod_dir, progress_bar=False)
        try:
            downloader.start(blocking=False)
        except:
            self.label_status["text"] = "Cant reach {}".format(content.name)

        self.button_action.place(x=380, y=545)

        while not downloader.isFinished():
            if is_close:
                break
            self.label_speed["text"] = downloader.get_speed(human=True)
            self.label_eta["text"] = downloader.get_eta(human=True)
            self.progressbar["value"] = downloader.get_progress()*100
            self.label_status["text"] = ("{} {} ({}/{}) | {} files in queue").format(
                downloader.get_status(),
                content.name,
                downloader.get_dl_size(human=True),
                tools.size_format(downloader.filesize),
                str(len(to_download))
            )
            sleep(0.2)

        if is_close:
            return True

        if downloader.isSuccessful():
            self.label_status["text"] = "Downloading {} completed".format(
                content.name)
            to_download.remove(content)
            self.label_status["text"] = "Unziping..."
            is_unzipped = tools.unzip(content.url, gmod_dir)
            if is_unzipped[0]:
                self.label_status["text"] = "Completed {}".format(content.name)
            else:
                self.label_status["text"] = "Unziping {} FAILED! You have to unzip it manualy.".format(
                    is_unzipped[1]
                )
            if to_download == []:
                self.button_action["text"] = "Exit"

            print(to_download)
            return True
        else:
            self.label_status["text"] = "Downloading {} FAILED!".format(
                content.name)
            return False
0

Nie da się Tobie pomóc w tym momencie. Jedyna rada to rozbicie problemu na mniejsze elementy i wskazanie nam, co nie działa tak, jakbyś chciał, by działało.

0

No wlasnie tyle wiem ze cos prawdobnie z petla nie gra.
Jak wybieram jeden element do pobrania to wszystko dziala, gdy wybieram 2 pobiera tylko 1, gdy wybieram 3 pobiera tylko 2.
No i dajmy ze pobieram 2 elementy, to po pobraniu 1, petla po prostu sie przerywa.

0

Która konkretnie? W Twoim przytoczonym kodzie są dwie pętle for.

0

@Pyxis:

self.downloaded = []
for con in to_download:
    self.downloaded.append(self.start_download(con))
if to_download == []:
    self.button_action["text"] = "Exit"
1

Powodem jest to, że iterujesz po "zmiennym" obiekcie (mam na myśli mutable object), jakim jest lista i jednocześnie wykonujesz na nim operację usuwania zawartości. Robisz mniej więcej coś takiego:

def rm_list_element(item):
    L.remove(item)

N = 2
L = [i for i in range(N)] # [0, 1]

for l in L:
    rm_list_element(l)

Po tej operacji L = [1], czyli usunęło Ci tylko jeden element. Gdy zainicjujesz N = 3, otrzymasz również L[1], czyli tym razem usunęło Ci tylko dwa elementy.

W Twoim kodzie odpowiednikiem listy L jest to_download. Odpowiednikiem funkcji rm_list_element jest metoda start_downaload (linia 193), a samo usuwanie elementów z listy występuje w linii 228. Pętlę po której iterujesz, już znalazłeś ;)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.