Python 子进程循环运行两次
Posted
技术标签:
【中文标题】Python 子进程循环运行两次【英文标题】:Python Subprocess Loop runs Twice 【发布时间】:2021-12-30 12:16:42 【问题描述】:所以,我创建了一个 Python 脚本来使用 Ghostscript 批量转换 PDF 文件。理想情况下它应该可以工作,但我不确定为什么它不工作。目前,它会检查输入的 PDF 文件两次,第二次运行时会覆盖输出文件。
这是脚本。
from __future__ import print_function
import os
import subprocess
try:
os.mkdir('compressed')
except FileExistsError:
pass
for root, dirs, files in os.walk("."):
for file in files:
if file.endswith(".pdf"):
filename = os.path.join(root, file)
arg1= '-sOutputFile=' + './compressed/' + file
print ("compressing:", file )
p = subprocess.Popen(['gs', '-sDEVICE=pdfwrite', '-dCompatibilityLevel=1.4', '-dPDFSETTINGS=/screen', '-dNOPAUSE', '-dBATCH', '-dQUIET', str(arg1), filename], stdout=subprocess.PIPE).wait()
这是输出。
我错过了我做错了什么。
【问题讨论】:
file
只是文件的名称。您在不同的目录中有多个名称相同的文件
@Jean-FrançoisFabre 我在那个文件夹中只有这 6 个文件。
但是compressed
也被扫描了,因为它在.
中!!
请don’t post images of code, error messages, or other textual data.
【参考方案1】:
file
只是文件名。您在不同的目录中有多个名称相同的文件。不要忘记os.walk
默认在子目录中递归。
因此您必须将转换后的文件保存在依赖于root
的目录或名称中。
并将输出目录放在当前目录之外,因为os.walk
会扫描它
例如,对于平面输出替换:
arg1= '-sOutputFile=' + './compressed/' + file
通过
arg1= '-sOutputFile=' + '/somewhere/else/compressed/' + root.strip(".").replace(os.sep,"_")+"_"+file
表达式
root.strip(".").replace(os.sep,"_")
应该创建一个“平面”版本的root
树,没有当前目录(无点)和转换为下划线的路径分隔符,加上最后一个下划线。这是一种可行的选择。
不会扫描./compressed
或任何其他子目录(可能更多您正在寻找的)的替代版本将使用os.listdir
代替(无递归)
root = "."
for file in os.listdir(root):
if file.endswith(".pdf"):
filename = os.path.join(root, file)
arg1= '-sOutputFile=' + './compressed/' + file
print ("compressing:", file )
或os.scandir
root = "."
for entry in os.scandir(root):
file = entry.name
if file.endswith(".pdf"):
filename = os.path.join(root, file)
arg1= '-sOutputFile=' + './compressed/' + file
print ("compressing:", file )
【讨论】:
感谢os.listdir(root)
,这正是我想要的。
如果您不关心顺序,os.scandir(root)
通常更快,但如果您只有几个文件,差异会很小。
scandir
在 Windows 上肯定要快得多,确实如此,但在上述情况下,它与没有其他操作(例如 os.getmtime()
或 stat
调用)相同。跨度>
【参考方案2】:
您的问题是 os.walk 也会在“压缩”目录中检索该内容。这是因为文件将在该目录中的 os.walk 列表文件之前被压缩和创建。如果您将print(os.path.join(root, file))
添加到您的 for 循环中,您会注意到这一点。
Bellow 是一个有效的 sn-p,因为检索到的文件只是当前目录中的文件。
import os
os.makedirs("compressed", exist_ok=True)
for file in os.listdir("."):
if not os.path.isfile(file):
continue
if not file.endswith(".pdf"):
continue
print(file)
【讨论】:
【参考方案3】:os.walk
将根据定义进入子目录,因此您将再次压缩compressed
子目录中的文件。
也许你只是想要
for file in os.scandir("."):
...
顺便说一句,您几乎肯定希望避免使用Popen
,而使用subprocess.run()
或其旧版本之一。
【讨论】:
【参考方案4】:在第一次迭代
for root, dirs, files in os.walk(".")
在当前目录中找到文件,然后将它们压缩到
./compressed/*.pdf
路径。
之后外循环的第二次迭代将在子目录中找到已经压缩的文件。
最简单的解决方法是将输出目录移到输入目录之外(或在compressed
目录旁边创建一个input
目录,并从那里读取文件而不是.
)
【讨论】:
以上是关于Python 子进程循环运行两次的主要内容,如果未能解决你的问题,请参考以下文章