def ftpwalk(ftp, top, topdown=True, onerror=None):
    """
    Generator that yields tuples of (root, dirs, nondirs).
    """
    # Make the FTP object's current directory to the top dir.
    ftp.cwd(top)

    # We may not have read permission for top, in which case we can't
    # get a list of the files the directory contains.  os.path.walk
    # always suppressed the exception then, rather than blow up for a
    # minor reason when (say) a thousand readable directories are still
    # left to visit.  That logic is copied here.
    try:
        dirs, nondirs = _ftp_listdir(ftp)
    except os.error, err:
        if onerror is not None:
            onerror(err)
        return

    if topdown:
        yield top, dirs, nondirs
    for entry in dirs:
        dname = entry[0]
        path = posixjoin(top, dname)
        if entry[-1] is None: # not a link
            for x in ftpwalk(ftp, path, topdown, onerror):
                yield x
    if not topdown:
        yield top, dirs, nondirs

    Generator that yields tuples of (root, dirs, nondirs).
    
recipes/Python/499334_Remove_FTP_directory_walk/recipe-499334.py