d2l-ai/d2l-zh · error · AssertionError
Only zip/tar files can be extracted
Error message
Only zip/tar files can be extracted
What it means
download_extract in contrib/to-rm-mx-contrib-text/d2lzh/text/embedding.py downloads a pretrained-embedding file with gluon.utils.download and then dispatches on its extension: '.zip' opens a ZipFile, '.tar'/'.gz' open a tarfile. Any other extension hits assert False, 'Only zip/tar files can be extracted' — the helper has no code path for non-archive files. It fires when the requested pretrained file, after download, is not one of the archive formats the function knows how to extract.
Source
Thrown at contrib/to-rm-mx-contrib-text/d2lzh/text/embedding.py:41
if not os.path.exists(path):
os.makedirs(path)
def download(embedding_name, pretrained_file_name, cache_dir=os.path.join('..', 'data')):
url, sha1 = PRETRAINED_FILE[embedding_name][pretrained_file_name]
mkdir_if_not_exist(cache_dir)
return gluon.utils.download(url, cache_dir, sha1_hash=sha1)
def download_extract(embedding_name, pretrained_file_name, folder=None):
"""Download and extract a zip/tar file."""
fname = download(embedding_name, pretrained_file_name)
base_dir = os.path.dirname(fname)
data_dir, ext = os.path.splitext(fname)
if ext == '.zip':
fp = zipfile.ZipFile(fname, 'r')
elif ext in ('.tar', '.gz'):
fp = tarfile.open(fname, 'r')
else:
assert False, 'Only zip/tar files can be extracted'
fp.extractall(base_dir)
if folder:
return os.path.join(base_dir, folder)
else:
return data_dir
def get_pretrained_file_names(embedding_name=None):
if embedding_name is not None:
return PRETRAINED_FILE[embedding_name].keys()
else:
return PRETRAINED_FILE
def create(embedding_name, pretrained_file_name, vocabulary=None):
return TokenEmbedding(embedding_name, pretrained_file_name.lower(), vocabulary)
class TokenEmbedding:
"""Token Embedding."""
def __init__(self, embedding_name, pretrained_file_name, vocabulary=None):View on GitHub (pinned to e6b18ccea7)
Solutions
- Check the actual downloaded file's extension with os.path.splitext; if it is a raw embedding file (.vec/.txt/.bin/.npy), do not call download_extract — use download() and consume the file directly, since there is nothing to extract.
- If the archive uses a format the branch misses (e.g. '.tar.bz2', '.tgz', '.ZIP'), normalize the check: use fname.lower() and cover '.zip', '.tar', '.gz', '.tgz', '.bz2', '.xz' with the matching tarfile.open mode ('r:*' handles all tar variants).
- If you control PRETRAINED_FILE, point the entry at a .zip or .tar/.gz archive of the embedding so download_extract's contract is satisfied.
- Verify the download actually succeeded and is not an HTML error page saved under a wrong name (gluon.utils.download without a matching sha1_hash can save a redirect page whose extension still trips the assert).
- Prefer the newer d2l package's token-embedding APIs over the legacy contrib/to-rm-mx-contrib-text module if you are not bound to old Gluon code.
Example fix
# before
fname = download(embedding_name, pretrained_file_name)
data_dir, ext = os.path.splitext(fname)
if ext == '.zip':
fp = zipfile.ZipFile(fname, 'r')
elif ext in ('.tar', '.gz'):
fp = tarfile.open(fname, 'r')
else:
assert False, 'Only zip/tar files can be extracted'
# after (tolerant extension handling, tarfile 'r:*' auto-detects compression)
fname = download(embedding_name, pretrained_file_name)
data_dir, ext = os.path.splitext(fname)
ext = ext.lower()
if ext == '.zip':
fp = zipfile.ZipFile(fname, 'r')
elif ext in ('.tar', '.gz', '.tgz', '.bz2', '.xz'):
fp = tarfile.open(fname, 'r:*')
else:
raise ValueError(f'Nothing to extract for non-archive file {fname}; use download() directly')
fp.extractall(os.path.dirname(fname)) Defensive patterns
Strategy: validation
Validate before calling
import os
EXTRACTABLE = {'.zip', '.tar', '.gz', '.tgz', '.bz2', '.xz'}
fname = download(embedding_name, pretrained_file_name)
_, ext = os.path.splitext(fname)
if ext.lower() not in EXTRACTABLE:
# raw embedding file: nothing to extract, consume it directly
embedding_path = fname
else:
embedding_path = download_extract(embedding_name, pretrained_file_name) Type guard
def is_extractable_archive(path) -> bool:
_, ext = os.path.splitext(path)
return ext.lower() in ('.zip', '.tar', '.gz', '.tgz', '.bz2', '.xz')
# usage
fname = download(embedding_name, pretrained_file_name)
if not is_extractable_archive(fname):
raise ValueError(f'{fname} is a raw file; call download() and skip extraction') Try / catch
try:
out_dir = download_extract(embedding_name, pretrained_file_name)
except AssertionError as e:
fname = download(embedding_name, pretrained_file_name)
raise RuntimeError(
f'download_extract cannot handle {os.path.splitext(fname)[1]!r}; '
f'if it is a raw embedding file, use download() and read it directly') from e Prevention
- Before calling download_extract, inspect the extension of the filename registered in PRETRAINED_FILE and confirm it is an archive the function supports.
- When registering new embeddings, prefer shipping them as .zip or .tar/.gz archives, matching what download_extract expects.
- Normalize extensions with ext.lower() so '.ZIP' or '.TAR' entries do not fall into the assert branch.
- Use tarfile.open(fname, 'r:*') when you control the code — it auto-detects gz/bz2/xz compression and removes most extension dispatch.
- Verify downloads with the sha1_hash argument of gluon.utils.download so a corrupted or redirect-page file is caught before extension dispatch.
When it happens
Trigger: Calling download_extract(embedding_name, pretrained_file_name) where PRETRAINED_FILE[embedding_name] maps to a plain (non-archive) file such as a '.bin', '.vec', '.txt', or '.npy' embedding; or passing a custom pretrained_file_name whose extension is not .zip/.tar/.gz. Also triggered by case-sensitivity mistakes ('.ZIP', '.TAR') since os.path.splitext comparison is exact, and by compound extensions like '.tar.bz2' (ext is '.bz2', not in the allowed set).
Common situations: Trying to load fastText/GloVe/word2vec files shipped as raw binaries or text instead of zips; adding a new embedding to PRETRAINED_FILE without checking how the file is actually packaged; renaming or re-hosting a pretrained file so its extension changes; older d2lzh versions whose extension list ('.tar', '.gz') misses formats like .bz2/.xz that newer archives use; typos or uppercase extensions in the file name map.
Related errors
- f"{name} 不存在于 {DATA_HUB}"
- 只有zip/tar文件可以被解压缩
- f"{name} 不存在于 {DATA_HUB}"
- 只有zip/tar文件可以被解压缩
- f"{name} 不存在于 {DATA_HUB}"
AI-assisted analysis of d2l-ai/d2l-zh@e6b18ccea7 (2026-08-14).
Data as JSON: /api/errors/9ecde8ad691b458e.
Report an issue: GitHub.