代码-
#Python Code
import os
from PIL import Image
path1 = sys.argv[1]
path2 = sys.argv[2]
if not os.path.exists(path2):
os.makedirs(path2)
for filename in os.listdir(path1):
if filename.endswith(".jpg"):
# print(filename.split(".")[0])
im = Image.open(f"{path1}{filename}")
# print(Image.open(f"{path1}{filename}"))
im.save(f"{path2}/{filename.split('.')[0]}.png", "png")
print("Lets go")
#1 楼
没有太多改进,只是做一些小的整理工作。帮助最终用户!
如果我使用此脚本,却忘了放一个或两个脚本时文件路径的数量,将出现以下错误:
IndexError: list index out of range
。此错误不会对用户有很大帮助。请考虑以下问题:try:
path1 = sys.argv[1]
path2 = sys.argv[2]
except IndexError:
raise Exception("Usage: python3 jpg_to_png.py <path to input folder> <path to output folder>")
这向用户提供了有关如何使用脚本的详细消息。
删除注释的代码。
不再需要的代码会增加无用的混乱,并使您的代码难以阅读。
评论
\ $ \ begingroup \ $
谢谢Linny,我将通过使用您的建议来改进代码,并感谢您对注释掉的代码的建议。
\ $ \ endgroup \ $
– Praguru 14
20-2-12在4:10
\ $ \ begingroup \ $
@Praguru有人回答您的问题后,您不应该编辑代码。您可以回滚您的编辑以使他们的answrr有效为agian吗?
\ $ \ endgroup \ $
–S.S. Anne
20-2-12在4:27
\ $ \ begingroup \ $
更好的方法是只使用argparse库。
\ $ \ endgroup \ $
– AleksandrH
20-2-12在14:36
\ $ \ begingroup \ $
每次进行argparse投票
\ $ \ endgroup \ $
–莫格说要恢复莫妮卡
20-2-13在12:53
\ $ \ begingroup \ $
尽管argparse很方便,但使用起来却很痛苦,对于完成一项任务的小型项目,它只会造成imo的障碍。
\ $ \ endgroup \ $
–以前
20-2-14在13:21
#2 楼
变量名称path1
和path2
不好,因为它们的描述性不强。它们应该是srcdir
和dstdir
(如果您更喜欢缩写),或者如果要拼写它们,则应该是source_directory
和destination_directory
。而不是操纵字符串,最好使用
pathlib
库,该库具有方便的功能with_suffix
。您应该测试具有多个点的文件名会发生什么,以防止丢失部分文件名而引起意外。
#3 楼
除了已经提到的内容外,我想指出的是,文件
super.picture.jpg
将被转换为super.png
如果有人循环运行您的程序并遍历文件夹,这可能是一个问题带有名为
anniversary.1.jpg
的文件q.4312079q .... 相反,因为您使用过
anniversary.2.jpg
,所以只能使用长度为endswith('.jpg')
的子字符串。评论
\ $ \ begingroup \ $
这不适用于.jpeg。与其使用子字符串,不如考虑使用os.path.splitext。它可以正确说明此用例,甚至更一般的用例。 OP可以扩展此脚本,以将指定格式的所有图像转换为另一种格式。另外,也可以只搜索字符串末尾的第一个句点,然后在其中分割。但是最好使用现有的库。
\ $ \ endgroup \ $
– AleksandrH
20-2-12在16:53
#4 楼
考虑使用__main__
使脚本更易于导入(请参阅此处)。此外,请考虑使用函数来隔离不同的步骤,以便将来更容易添加新功能。 br />
最后一件事,您可以使用更明确的日志消息,类似于
Converting {filename} from jpg to png
而不是Lets go
,也许可以使用logging
模块而不是简单的打印。评论
\ $ \ begingroup \ $
我怀疑其意图是将此脚本导入其他Python源文件中。这听起来更像一个独立的脚本。
\ $ \ endgroup \ $
– AleksandrH
20-2-12在14:37
\ $ \ begingroup \ $
@AleksandrH表示同意,但是,如果没有过度使用,则为这种将来不可预见的用例做准备也不会有害,例如在这种情况下。另外,获得更好的模块化和体系结构始终是一个好习惯。
\ $ \ endgroup \ $
–bracco23
20-2-12在14:40
\ $ \ begingroup \ $
是的,这很公平。仅将所有内容包装在__main__检查中并不需要太多的努力。
\ $ \ endgroup \ $
– AleksandrH
20-2-12在16:56
#5 楼
函数我将其抽象为可以调用的函数。然后,您还可以轻松地进行一些检查,以查看源路径是否确实是目录,目的地路径是否确实存在,......
pathlib.Path
有很多有助于文件路径处理的便捷方法。
from PIL import Image
from pathlib import Path
def convert_jpg_to_png(
source: Path,
destination: Path,
overwrite=False,
) -> None:
if not source.is_dir():
raise ValueError(f"{source} is not a directory")
if not source.exists():
raise ValueError(f"{source} does not exist")
if not destination.is_dir():
raise ValueError(f"{destination} is not a directory")
if not destination.exists():
destiny.mkdir(parents=True)
for source_name in source.glob("**/*.jpg"):
# If you want to cover both jpg and jpeg,
# for source_image in source.glob("**/*"):
# if not source_image.suffix.lower in {".jpg", ".jpeg"}:
# continue
destination_name = destination / (
source_name.relative_to(source.with_suffix(".png"))
)
if destination_name.exists() and not overwrite:
print(f"{destination_name} already exists")
continue
print(f"renaming {source_name} to {destination_name}")
with Image.open(source_name) as im:
im.save(destination_name, format="PNG")
如果您还想转换.JPG,.JPEG和.jpeg,
主后卫
然后可以将您的逻辑隐藏在
if __name__ == "__main__":
后卫后面,以便以后可以在需要的其他程序中导入此模块:if __name__ == "__main__":
if len(sys.argv) == 1:
source = Path(".") # default: current location
destination = source
overwrite = False
source = Path(sys.argv[1])
if len(sys.argv) > 2:
if sys.argv[2] in {"True", "False"}:
destination = source
overwrite = sys.argv[2] == "True"
else:
destination = Path(sys.argv[2])
else:
destination = source
overwrite = False
if len(sys.argv) > 3:
overwrite = sys.argv[3] == "True"
convert_jpg_to_png(source, destination, overwrite)
我在这里手动处理了参数,但是您可以更好地检查
argparse
模块来简化此操作#6 楼
通常,代码简单明了。取决于目标用途,除了其他答案建议之外,我还要添加:
对文件结尾的支持在“。jpeg”上不仅是.jpg;
同样,我将使文件名过滤器还查找大写或大小写混合的JPEG文件;
如果我不得不处理不可靠的源,我还将添加Image.verify()和/或imghdr检查是否获得了有效的jpeg文件,否则给出有意义的错误消息。
#7 楼
我建议您执行以下操作:可以使用生成器表达式过滤文件列表来删除嵌套级别:
files_to_convert = (f for f in os.listdir(path1) if f.endswith(".jpg"))
for filename in files_to_convert:
... process the file ...
确保
*.jpg
的列表是文件,而不是名为*.jpg
的子目录:files_to_convert = (f for f in os.listdir(path1) if f.endswith(".jpg") and os.path.isfile(f))
使用
os.path.join
构造路径:im = Image.open(os.path.join(path1, filename))
使用
os.path.splitext
拆分文件名:root, _ = os.path.splitext(filename)
png_file = os.path.join(path2, f'{root}.png')
im.save(png_file, "png")
评论
欢迎来到代码审查。我回滚了您的上一次编辑。请不要更新问题中的代码以合并答案的反馈,这与代码审查的“问题+答案”风格背道而驰。这不是您应该在其中保留最新版本的论坛。收到答案后,请查看您可能会做什么和可能不会做什么。根据您的用例和预期的用户群,考虑是否有人可以尝试使用python test.py foo / img.jpg bar / img.png或python test.py in / out /(其中存在in / foo.jpeg)。
略有切线,可能值得注意的是,将JPEG图像转换为PNG格式而不进行清理以消除压缩伪像几乎几乎没有实际用处。它只会使文件(可能很多次)变大而不会以任何方式提高图像的质量。 (当然,在某些情况下可能会出现异常,例如,如果您尝试将图像馈送到可以解析PNG但不能解析JPEG的程序中。)
您是否真的要为每个文件打印一次(“放手”)?
我在这里比Ilmari还要走得更远,说如果我承担了这项任务,我将不得不告诉我的雇主,如果您认为您需要将JPEG转换为PNG的工具,那么您的流程几乎肯定有问题整体上您基本上是将水从1加仑的水桶倒入5加仑的水桶;您仍然只有1加仑。找出您的过程中哪些环节失去了其他四个环节,并予以消除。