4

I'm using pytube to convert a url that is for sure a link to a YouTube playlist into a pytube.Playlist()

if "/playlist?list=" in url:
        playlist = Playlist(url)
        if len(playlist.video_urls._elements) == 0:
                print("Some error message")

The problem is that the playlist I'm using to test this has about 300 videos in it, so this if statement should be skipped, but instead, it goes into it and prints the error message. So naturally, I went to check it out with the debugger, and for some reason, once I start stepping into the code, it works the way it should and skips the if statement.

Anyone know what might be the problem?

IDE: Visual Studio Code

OS: Windows 10

MyPing0
  • 63
  • 4

1 Answers1

2

Playlist.video_urls is a DeferredGeneratorList, not a list. So until you iterate over it, it doesn't have a length.

@property  # type: ignore
@cache
def video_urls(self) -> DeferredGeneratorList:
    """Complete links of all the videos in playlist
    
    :rtype: List[str]
    :returns: List of video URLs
    """
    return DeferredGeneratorList(self.url_generator())

Moreover, you're checking the length of _elements which is private to the class/API. And it's initialised to an empty list so it's length is always initially zero.

So either call len() on playlist.video_urls or better, use the provided method to populate the list generate_all() or just call list() on it.

The reason it works in your debugger is that the debugger tries to access the elements of the list to find its length, which triggers the iteration and populates it.

Good on you for at least trying the debugger and noticing the difference in behaviour for normal execution vs debugger execution! +1

And instead of checking the length, just iterate over it and check if anything was done, with a flag value:

if "/playlist?list=" in url:
    playlist = Playlist(url)
    had_videos = False  # initial value
    for video in playlist.video_urls:
        had_videos = True  # if exec gets here, you had at least one vid
        # do something with each `video`
    if not had_videos:
        print("Some error message")
aneroid
  • 12,983
  • 3
  • 36
  • 66