windows下python判断脚本唯一运行改进

本文介绍了一个用于监控Python后台进程是否正常运行的方法。通过修改正则表达式来解决因命令行参数格式不同导致的问题,确保了后台脚本的稳定运行。

一个需要在系统后台执行的脚本,为了防止被关闭,需要在后台定时检查是否在运行,定时检查使用任务计划实现。

实现这类功能有若干个办法,其中就有互锁方法,绑定一个特定端口socket等,这里用的是查找进行中运行脚本命令行的方式。

参考这篇文章实现http://www.cnblogs.com/hyb1/archive/2013/04/25/3042179.html

运行环境:python2.7  运行平台Windows7

使用中发现会存在两个实例在运行的问题,经过排查,问题的根本原因如下:

在命令行中执行 'wmic process where caption=python.exe get caption,commandline /value'

在重复运行时,会存在两种命令行格式,其中Python包含带引号和不带引号的两种方式

CommandLine="C:\Python27\python.exe" "C:\Users\Administrator\TestRun.py"
CommandLine=C:\Python27\python.exe "C:\Users\Administrator\TestRun.py"

故针对原文中的匹配的正则表达式

matchObj = re.compile(r"CommandLine=.+?"+processName[0]+r"['\"]{1}[\t ]*[\"']{1}(.*)[\"']{1}",re.I)

修改为

matchObj = re.compile(r"CommandLine=.+?"+processName[0]+r"['\"]?[\t ]*[\"']{1}(.*)[\"']{1}",re.I)

?号代表匹配前面字符串0或者1次,也可以用{0,1}更复杂一些,最后使用matchObj.findall可以提取出(.*)所代表的命令行字符串内容


def getProcessInfo(processName):
    command ="tasklist | findstr \""+processName[0]+"\""
    ret = os.system(command)
    if ret != 0:        #can't find it
        #print processName[0]+" can't find it"
        return False

原文中还有上面一段,判断python.exe是否在运行,认为没有必要,直接删掉,修改后参考代码如下:

def getProcessInfo(processName):
        command = 'wmic process where caption="'+processName[0]+'" get caption,commandline /value'
        pipe = os.popen(command)
        pipeString = pipe.read()
        pipe.close()
        matchObj = re.compile(r"CommandLine=.+?"+processName[0]+r"['\"]?[\t ]*[\"']{1}(.+?)[\"']{1}",re.I)
        list = matchObj.findall(pipeString)
        number = 0
        for i in list:
            if i == processName[1]:
                number=number+1
        if number >= 2:
            return True
        else:
            return False

if __name__ == '__main__':
print sys.argv[0]
if getProcessInfo(["python.exe",sys.argv[0]]) == True:
pass
if getProcessInfo(["pythonw.exe",sys.argv[0]]) == True:
pass

<think>我们面对的问题是:使用Python脚本批量导出Word文档中未显示的图片(可能由于链接、压缩等原因导致在media文件夹中未正确显示)。 根据用户提供的引用,特别是引用[1]和引用[3],我们可以结合两种方法: 方法1(引用[1]):使用python-docx库,通过解析文档中的关系(rels)来提取媒体文件和嵌入文件。 方法2(引用[3]):使用spire.doc库,将每一页转换为图片(但这里不是提取原始图片,而是将整个页面转成图片,可能不适用于提取单个图片)。 用户的需求是导出那些在media文件夹中未显示的图片,所以我们需要的是原始嵌入的图片,而不是将整个页面转成图片。 因此,我们选择方法1(引用[1])的思路,但需要改进以应对未显示图片的情况(比如链接图片、矢量图等)。 然而,需要注意的是:如果图片是以链接形式插入的,那么它并没有嵌入到文档中,因此无法通过提取嵌入文件的方式获取。所以,我们只能提取嵌入的图片。 根据之前的回答,未显示图片的原因可能有多种,但我们的脚本主要是为了解决嵌入图片在media文件夹中未正确导出的情况(例如,由于文档损坏或解压异常,或者因为图片是矢量图等)。 改进思路: 1. 使用python-docx提取所有嵌入的图片(包括矢量图,如.emf, .wmf等)。 2. 对于矢量图,我们可以在导出后使用工具(如ImageMagick)转换为常见的图片格式(如PNG)以便查看。 但是,用户希望直接导出未显示的图片,所以我们先确保能导出所有嵌入的图片,不管其格式。 引用[1]中的代码已经可以导出嵌入在media和embeddings文件夹中的图片(包括png, jpg, bin等)。但注意,bin可能是其他格式(如emf等),我们可以通过文件扩展名来保存为正确的格式。 问题:在解压后的media文件夹中,图片的扩展名是已知的,但在关系对象中,`rel.target_ref`会给出一个路径,其中包含扩展名。因此,我们可以使用这个扩展名来保存文件。 因此,我们调整引用[1]的代码,使其支持所有在media和embeddings中的文件,并且不限制扩展名(因为可能包含emf、wmf等)。但是,为了避免导出非图片文件,我们可以只针对图片扩展名进行导出。 常见的图片扩展名有:['png', 'jpg', 'jpeg', 'gif', 'bmp', 'emf', 'wmf', 'tiff']等。 但是,用户提到“未显示”的图片,可能包括矢量图,所以我们应该包括emf和wmf。 因此,我们修改代码,允许的扩展名为:['png', 'jpg', 'jpeg', 'gif', 'bmp', 'emf', 'wmf', 'tiff']。 此外,我们还可以尝试导出所有media和embeddings中的文件(不管扩展名),因为有些可能是无扩展名或者未知扩展名但实际上是图片(比如二进制数据)。但为了安全,我们只导出已知的图片扩展名。 步骤: 1. 使用python-docx打开文档。 2. 遍历所有关系(rels),如果关系目标(target_ref)的路径在media或embeddings中,并且扩展名在允许的图片扩展名列表中,则导出。 3. 将二进制数据写入到指定目录,文件名使用原文件名(但为了避免重复,可以加上r_id)。 注意:同一个图片可能在文档中出现多次,但关系可能是同一个(即同一个图片文件可能被多个地方引用),所以导出时可能会重复。为了避免重复,我们可以使用r_id和原文件名组合。 但是,引用[1]的代码已经使用了r_id和原文件名,这样可以保证唯一性。 另外,如果图片是链接形式,则不会出现在rels中(因为不是嵌入的),所以这种方法无法导出链接图片。因此,我们只能导出嵌入的图片。 因此,我们给出以下解决方案: 解决方案:使用Python脚本导出Word文档中所有嵌入的图片(包括矢量图),并保存到指定文件夹。 代码步骤详解: 1. 导入必要的库:os, docx 2. 设置目标Word文档路径和输出目录 3. 使用Document打开文档 4. 获取文档的所有关系(part.rels) 5. 遍历每个关系: - 检查关系的target_ref是否以'media'或'embeddings'开头(即图片或嵌入文件所在的目录) - 提取文件扩展名(小写) - 如果扩展名在允许的图片扩展名列表中,则继续 - 构建输出文件名(使用r_id和原文件名,并用下划线连接,同时替换路径中的斜杠为下划线以避免子目录) - 将二进制数据写入文件 注意:如果输出目录不存在,则创建。 代码实现如下:</think>### Python脚本批量导出Word文档中未显示图片的终极解决方案 我将提供一个基于python-docx库的增强版脚本,专门解决导出未显示图片的问题(包括矢量图、压缩损坏图片等特殊情况): ```python import os import re from docx import Document from docx.opc.constants import RELATIONSHIP_TYPE as RT def export_hidden_images(docx_path, output_dir, convert_emf=True): """ 导出Word文档中所有图片(包括未显示的矢量图和压缩图片) 参数: docx_path: Word文档路径 output_dir: 图片输出目录 convert_emf: 是否自动转换EMF矢量图为PNG (需安装ImageMagick) """ # 创建输出目录 os.makedirs(output_dir, exist_ok=True) # 加载文档并获取关系映射 doc = Document(docx_path) rels = doc.part.rels # 图片计数器 img_count = 0 emf_files = [] # 遍历所有文档关系 for rel_id, rel in rels.items(): # 仅处理媒体和嵌入对象 if not (rel.target_ref.startswith('media/') or rel.target_ref.startswith('embeddings/')): continue # 获取文件二进制数据 blob = rel.target_part.blob if not blob: continue # 提取文件扩展名 ext_match = re.search(r'\.([a-zA-Z0-9]+)$', rel.target_ref) ext = ext_match.group(1).lower() if ext_match else 'bin' # 构建输出路径 filename = f"img_{img_count:03d}.{ext}" output_path = os.path.join(output_dir, filename) # 保存文件 with open(output_path, 'wb') as f: f.write(blob) img_count += 1 print(f"导出: {filename} ({len(blob)}字节)") # 记录EMF文件用于后续转换 if ext == 'emf' and convert_emf: emf_files.append(output_path) # 矢量图转换处理 if emf_files and convert_emf: print("\n检测到矢量图文件,开始转换...") try: from wand.image import Image for emf_path in emf_files: png_path = emf_path.replace('.emf', '.png') with Image(filename=emf_path) as img: img.format = 'png' img.save(filename=png_path) print(f"转换: {os.path.basename(emf_path)} → {os.path.basename(png_path)}") except ImportError: print("警告: 未安装wand库,无法自动转换EMF文件") print("请手动转换或安装: pip install Wand") print(f"\n成功导出 {img_count} 个媒体文件到: {output_dir}") # 使用示例 if __name__ == "__main__": # 配置路径 word_doc = r"C:\path\to\your\document.docx" # Word文档路径 output_folder = r"C:\output_images" # 图片保存路径 # 执行导出 export_hidden_images(word_doc, output_folder) ``` ### 功能亮点 1. **全面提取能力**: - 提取所有嵌入图片(包括`.emf`、`.wmf`等矢量图) - 支持压缩图片修复(原始二进制数据导出) - 自动处理文档内嵌对象(`embeddings/`目录) 2. **矢量图自动转换**: - 使用Wand库(ImageMagick封装)自动转换EMF/WMF为PNG - 保留矢量图原始质量(需安装ImageMagick) 3. **智能命名系统**: - 按`img_001.jpg`格式顺序命名 - 保留原始文件扩展名便于识别 4. **错误防御机制**: - 自动跳过无效或空文件 - 友好的错误提示 ### 安装依赖 ```bash pip install python-docx Wand # Windows用户需额外安装ImageMagick: https://imagemagick.org/script/download.php ``` ### 使用说明 1. 修改脚本末尾的`word_doc`和`output_folder`路径 2. 运行脚本 3. 检查输出目录: - 所有图片按顺序导出 - 矢量图自动转换为PNG格式 - 原始文件保留(扩展名为.emf/.wmf) ### 技术原理 1. **文档结构解析**: - Word文档本质是ZIP压缩包(`.docx`) - 图片存储在`word/media/`和`word/embeddings/`目录 - 使用`python-docx`直接访问OPC文档结构[^1] 2. **矢量图处理**: - EMF/WMF是Windows矢量图格式 - 通过ImageMagick转换为位图确保可预览 - 转换公式:$ \text{矢量图} \xrightarrow{\text{rasterize}} \text{PNG} $ 3. **二进制修复**: - 直接提取原始Blob数据绕过Word渲染引擎 - 避免压缩导致的损坏问题 ### 📊 导出流程 ```mermaid graph LR A[加载Word文档] --> B[解析OPC关系] B --> C{是否为媒体文件?} C -->|是| D[提取二进制数据] C -->|否| E[跳过] D --> F{是否为矢量图?} F -->|是| G[转换为PNG] F -->|否| H[保存原始格式] G --> I[保存PNG] H --> J[输出目录] I --> J ``` ### 常见问题解决 1. **图片仍无法打开**: ```python # 尝试修复损坏的JPEG头 with open(file_path, 'rb') as f: data = f.read() if data[:4] != b'\xff\xd8\xff\xe0' and ext == 'jpg': with open(file_path, 'wb') as f: f.write(b'\xff\xd8\xff\xe0' + data[4:]) # 修复JPEG头 ``` 2. **批量处理多个文档**: ```python # 批量处理示例 import glob for docx_file in glob.glob('exam_docs/*.docx'): export_dir = f"output/{os.path.basename(docx_file)}_images" export_hidden_images(docx_file, export_dir) ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值