Reputation: 9538
I am trying to convert images in folder named Final
to one pdf
This is my try to achieve the task
import os
import img2pdf
with open("Stickers.pdf","wb") as f:
#print(os.listdir("./Final"))
f.write(img2pdf.convert([x for x in os.listdir("./Final") if x.endswith(".png")]))
But I got an error message like that (any idea how to fix that)
File "C:\Users\Future\Desktop\demo.py", line 5, in <module>
f.write(img2pdf.convert([x for x in os.listdir("./Final") if x.endswith(".png")]))
File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\img2pdf.py", line 2263, in convert
) in read_images(
File "C:\Users\Future\AppData\Local\Programs\Python\Python39\lib\site-packages\img2pdf.py", line 1444, in read_images
im = BytesIO(rawdata)
TypeError: a bytes-like object is required, not 'str'
Upvotes: 4
Views: 3730
Reputation: 3518
The error message is cryptic largely because img2pdf
bends over backwards to be so versatile about what you can pass to the convert
function: a file path (as a string or path object), an open file object, raw image data, multiples of any of those, or a list of any of those. If given a string, it first treats it as a file path and tries to open it; if that fails, it then assumes the input must be raw image data (as bytes) and attempts to process it that way, in which case you get the TypeError
that you see.
The reason it can't open the files correctly is that os.listdir
returns only the file names themselves, not their full path, and those image files aren't in your current working directory. That is, you're trying to open example.png
, not ./Final/example.png
.
You can fix this by manually adding the folder name to each file name:
import os
import img2pdf
with open("Stickers.pdf", "wb") as f:
f.write(img2pdf.convert([f"./Final/{x}" for x in os.listdir("./Final") if x.endswith(".png")]))
You could also use pathlib
. It often makes dealing with paths easier (and more easily platform-independent) than messing about with os
. Path
objects are smarter than plain strings, and automatically know about their enclosing folder in this case.
All of Python's builtins (like open
) will accept a Path
object anywhere they already accept a string representing a path, and by this point practically all third-party libraries do as well.
This includes img2pdf, as of 0.5.0.
Here's what a very literal translation would look like, except using pathlib
:
from pathlib import Path
import img2pdf
with open("Stickers.pdf", "wb") as f:
f.write(img2pdf.convert([path for path in Path("./Final").glob("*.png")]))
But now that the glob
method's doing the filtering, the list comprehension isn't actually doing anything. We can't actually pass it the result of glob
, as that's a generator rather than a list, but we can unpack it to pass the individual results as multiple arguments.
from pathlib import Path
import img2pdf
with open("Stickers.pdf", "wb") as f:
f.write(img2pdf.convert(*Path("./Final").glob("*.png")))
Upvotes: 5
Reputation: 59
Please try this:
Instead of
[x for x in os.listdir("./Final") if x.endswith(".png")]
Try:
[open(x,'rb').read() for x in os.listdir("./Final") if x.endswith(".png")]
Upvotes: -1