Skip to content

ZipFile.Path print failed when built zip file is based on a bytes stream #109200

Closed as duplicate

Description

@the-cat-that-codes

Bug report

Bug description:

Hi,

The print() function of a zipfile.Path failed if the ZipFile is based on a bytes stream.
More generally, every try to display or build a path based on bytes stream ZipFile path seems to fail.

A zip file is needed for playing this use case.
The mine is composed like this :

folder_root
├── folder_depth1
│ ├── folder_depth2
│ │ ├── folder_depth3
│ │ │ └── Python-Logo.png
│ │ └── Python-Logo.png
│ └── Python-Logo.png
└── Python-Logo.png
and is named "my_package.zip"

To trigger the problem I type these commands :

from zipfile import ZipFile, Path as ZPath
from io import BytesIO

with open("my_package.zip", "rb") as f:
    my_bytes=BytesIO(f.read())

my_zf_from_file=ZipFile("my_package.zip")

for i in ZPath(my_zf_from_file).iterdir():
     print(i)
 
my_zf_from_bytes=ZipFile(my_bytes)
for i in ZPath(my_zf_from_bytes).iterdir():
     print(i)

Here is my output:

>>> from zipfile import ZipFile, Path as ZPath
>>> from io import BytesIO
>>> with open("my_package.zip", "rb") as f:
...     my_bytes=BytesIO(f.read())
... 
>>> my_zf_from_file=ZipFile("my_package.zip")
>>> for i in ZPath(my_zf_from_file).iterdir():
...      print(i)
... 
my_package.zip/folder_root/
>>> my_zf_from_bytes=ZipFile(my_bytes)
>>> for i in ZPath(my_zf_from_bytes).iterdir():
...      print(i)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python3.9/zipfile.py", line 2347, in __str__
    return posixpath.join(self.root.filename, self.at)
  File "/usr/lib/python3.9/posixpath.py", line 76, in join
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType

To have more information I wrote this function

def mywalk(top):
    dirs=[]
    files=[]
    for item in top.iterdir():
            if item.is_file():
                    files.append(item)
            elif item.is_dir():
                    dirs.append(item)
    yield top.name, dirs, files
    for d in dirs:
            for w in mywalk(d):
                    yield w

and then, launch it, like this

for w in mywalk(ZPath(my_zf_from_bytes)):
     print(w)
 
for w in mywalk(ZPath(my_zf_from_file)):
     print(w)

Here is my output:

>>> for w in mywalk(ZPath(my_zf_from_bytes)):
...      print(w)
...  
... 
('', [Path(None, 'folder_root/')], [])
('folder_root', [Path(None, 'folder_root/folder_depth1/')], [Path(None, 'folder_root/Python-Logo.png')])
('folder_depth1', [Path(None, 'folder_root/folder_depth1/folder_depth2/')], [Path(None, 'folder_root/folder_depth1/Python-Logo.png')])
('folder_depth2', [Path(None, 'folder_root/folder_depth1/folder_depth2/folder_depth3/')], [Path(None, 'folder_root/folder_depth1/folder_depth2/Python-Logo.png')])
('folder_depth3', [], [Path(None, 'folder_root/folder_depth1/folder_depth2/folder_depth3/Python-Logo.png')])
>>> 
>>> for w in mywalk(ZPath(my_zf_from_file)):
...      print(w)
... 
('', [Path('my_package.zip', 'folder_root/')], [])
('folder_root', [Path('my_package.zip', 'folder_root/folder_depth1/')], [Path('my_package.zip', 'folder_root/Python-Logo.png')])
('folder_depth1', [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/')], [Path('my_package.zip', 'folder_root/folder_depth1/Python-Logo.png')])
('folder_depth2', [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/folder_depth3/')], [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/Python-Logo.png')])
('folder_depth3', [], [Path('my_package.zip', 'folder_root/folder_depth1/folder_depth2/folder_depth3/Python-Logo.png')])

In the first case (zipfile path based on a bytes stream), the Path-like objects have 'None' as root when the root is the name of the package in the second case (zipfile path made based on the file).

My though is that a path is not intended to bring a NoneType element and so a path.join failed when a transformation into a string is needed.
What about change this "None" by an empty string ?

CPython versions tested on:

3.8, 3.9

Operating systems tested on:

Linux

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Nov 24, 2023
  2. barneygale commented on May 5, 2025

    @barneygale
    Contributor

    I think this is a duplicate of #100609, so I'll close this issue. Thanks for reporting all the same!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions