获取当前执行主脚本目录,sys.path.append导入模块

本文介绍了在Python中如何使用sys.argv[0]和__file__来获取当前执行脚本的路径,并展示了如何通过os模块获取文件所在目录的完整路径。此外,还提供了将外部模块路径添加到sys.path的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、在python下,获取当前执行主脚本的方法有两个:sys.argv[0]和__file__

sys.argv[0]
获取主执行文件路径的最佳方法是用sys.argv[0],它可能是一个相对路径;

_file__ 是用来获得模块所在的路径的,这可能得到的是一个相对路径,若按绝对路径执行则得到的是绝对路径;

获取文件所在目录的完整路径ABSPATH :

import os, sys
ABSPATH = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))

将参数1与路径拼接得到FRONTEND
FRONTEND = os.path.abspath(os.path.join(ABSPATH, sys.argv[1]))

执行test.py这个脚本:

[aaa@localhosttest]$ python test.py 123
/home/aaa/Desktop/test/123


2、将模块路径添加到程序中:

对于模块和自己写的程序不在同一个目录下,可以把模块的路径通过sys.path.append(路径)添加到程序中,引用test.py中的ABSPATH为例。

在程序开头加上:

import sys
sys.path.append(ABSPATH)  #sys.path.append(’引用模块的地址');将ABSPATH下的模块添加到程序中了

print sys.path #查看python导入文件或者模块

PS C:\Users\Administrator\Desktop> # PythonEnvRepair_Complete_Fix.ps1 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 1. 动态获取桌面路径(多级回退) PS C:\Users\Administrator\Desktop> $desktopPath = @( >> [Environment]::GetFolderPath([Environment+SpecialFolder]::Desktop), >> "C:\Users\Administrator\Desktop", >> "C:\Users\Public\Desktop", >> "C:\Windows\Desktop", >> "C:\Desktop" >> ) | Where-Object { Test-Path $_ } | Select-Object -First 1 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> if (-not $desktopPath) { >> $desktopPath = "C:\Temp" >> Write-Host "⚠️ 警告: 使用备用路径: $desktopPath" -ForegroundColor Yellow >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 2. 设置全局编码(强制UTF-8) PS C:\Users\Administrator\Desktop> [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 PS C:\Users\Administrator\Desktop> $env:PYTHONUTF8 = "1" PS C:\Users\Administrator\Desktop> $env:PYTHONIOENCODING = "utf-8" PS C:\Users\Administrator\Desktop> [Environment]::SetEnvironmentVariable("PYTHONUTF8", "1", "Machine") PS C:\Users\Administrator\Desktop> [Environment]::SetEnvironmentVariable("PYTHONIOENCODING", "utf-8", "Machine") PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 3. 终极修复函数 PS C:\Users\Administrator\Desktop> function global:Repair-PythonEnvironment { >> param( >> [string]$PythonPath = "E:\Python310", >> [switch]$Force = $false >> ) >> >> # 验证Python安装 >> $pythonExe = Join-Path $PythonPath "python.exe" >> if (-not (Test-Path $pythonExe)) { >> Write-Host "❌ 错误: 找不到python.exe: $pythonExe" -ForegroundColor Red >> return $false >> } >> >> # 获取Python版本信息 >> $versionInfo = & $pythonExe -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" >> $shortVersion = & $pythonExe -c "import sys; print(f'{sys.version_info.major}{sys.version_info.minor}')" >> >> # 创建site-packages目录(如果不存在) >> $sitePackages = Join-Path $PythonPath "Lib\site-packages" >> if (-not (Test-Path $sitePackages)) { >> New-Item -ItemType Directory -Path $sitePackages -Force | Out-Null >> Write-Host "创建site-packages目录: $sitePackages" -ForegroundColor Cyan >> } >> >> # 设置持久化环境变量 >> [Environment]::SetEnvironmentVariable("DESKTOP_PATH", $desktopPath, "User") >> [Environment]::SetEnvironmentVariable("DESKTOP_PATH", $desktopPath, "Machine") >> $env:DESKTOP_PATH = $desktopPath >> >> # 创建增强版sitecustomize.py >> $sitecustomizeContent = @" >> import sys >> import os >> import site >> import traceback >> import importlib.util >> import logging >> >> # 配置日志 >> log_path = os.path.join(os.path.expanduser('~'), 'python_env_fix.log') >> logging.basicConfig( >> filename=log_path, >> level=logging.INFO, >> format='%(asctime)s - %(levelname)s - %(message)s', >> encoding='utf-8' >> ) >> >> logger = logging.getLogger('PythonEnvFix') >> >> def ensure_path(path, priority=0): >> """确保路径在sys.path中""" >> abs_path = os.path.abspath(path) >> logger.info(f"处理路径: {abs_path}") >> >> # 创建目录(如果不存在) >> if not os.path.exists(abs_path): >> try: >> os.makedirs(abs_path) >> logger.info(f"创建目录: {abs_path}") >> except Exception as e: >> logger.error(f"创建目录失败: {abs_path}, 错误: {str(e)}") >> return False >> >> # 添加路径到sys.path >> if abs_path not in sys.path: >> try: >> if priority == 0: >> sys.path.insert(0, abs_path) # 最高优先级 >> else: >> sys.path.append(abs_path) # 最低优先级 >> logger.info(f"添加路径到sys.path: 优先级={priority}") >> except Exception as e: >> logger.error(f"添加路径到sys.path失败: {str(e)}") >> >> # 使用site模块添加路径 >> try: >> site.addsitedir(abs_path) >> logger.info(f"使用site.addsitedir添加路径") >> except Exception as e: >> logger.error(f"site.addsitedir失败: {str(e)}") >> >> # 验证路径可导入性 >> try: >> importlib.util.find_spec('__init__', [abs_path]) >> logger.info("路径可导入验证成功") >> except ImportError: >> logger.warning(f"路径不可导入: {abs_path}") >> >> return True >> >> # 主修复逻辑 >> try: >> desktop_path = os.environ.get('DESKTOP_PATH', '') >> if desktop_path: >> logger.info(f"开始修复路径: {desktop_path}") >> if ensure_path(desktop_path, priority=0): >> logger.info(f"路径添加成功: {desktop_path}") >> else: >> logger.error(f"路径添加失败: {desktop_path}") >> else: >> logger.error("DESKTOP_PATH环境变量未设置") >> >> # 刷新模块缓存 >> sys.path_importer_cache.clear() >> logger.info("模块缓存已刷新") >> >> except Exception as e: >> logger.error(f"修复过程中发生错误: {str(e)}") >> logger.error(traceback.format_exc()) >> "@ >> >> $sitecustomizePath = Join-Path $sitePackages "sitecustomize.py" >> Set-Content -Path $sitecustomizePath -Value $sitecustomizeContent -Encoding UTF8 >> Write-Host "创建sitecustomize.py: $sitecustomizePath" -ForegroundColor Cyan >> >> # 创建系统级.pth文件 >> $pthPath = Join-Path $sitePackages "desktop_path.pth" >> Set-Content -Path $pthPath -Value $desktopPath -Encoding UTF8 >> Write-Host "创建系统级.pth文件: $pthPath" -ForegroundColor Cyan >> >> # 创建用户级.pth文件 >> $userSitePath = Join-Path $env:APPDATA "Python\Python$shortVersion\site-packages" >> >> if (-not (Test-Path $userSitePath)) { >> New-Item -ItemType Directory -Path $userSitePath -Force | Out-Null >> Write-Host "创建用户site-packages目录: $userSitePath" -ForegroundColor Cyan >> } >> >> $userPthPath = Join-Path $userSitePath "desktop_path.pth" >> Set-Content -Path $userPthPath -Value $desktopPath -Encoding UTF8 >> Write-Host "创建用户级.pth文件: $userPthPath" -ForegroundColor Cyan >> >> # 在Python安装目录添加路径 >> $pythonPathFile = Join-Path $PythonPath "pythonpath.txt" >> Set-Content -Path $pythonPathFile -Value $desktopPath -Encoding UTF8 >> Write-Host "创建Python路径文件: $pythonPathFile" -ForegroundColor Cyan >> >> Write-Host "✅ Python环境修复完成" -ForegroundColor Green >> return $true >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 4. 全面诊断函数 PS C:\Users\Administrator\Desktop> function global:Test-PythonEnvironment { >> param( >> [string]$PythonPath = "E:\Python310", >> [switch]$Detailed = $false >> ) >> >> $pythonExe = Join-Path $PythonPath "python.exe" >> if (-not (Test-Path $pythonExe)) { >> Write-Host "❌ 错误: 找不到python.exe: $pythonExe" -ForegroundColor Red >> return $false >> } >> >> # 确保环境变量传递 >> $env:DESKTOP_PATH = $desktopPath >> >> # 生成诊断脚本 >> $testScript = @" >> import sys >> import os >> import site >> import traceback >> import importlib.util >> import platform >> import json >> >> # 收集诊断数据 >> diagnostic_data = { >> "system_info": { >> "python_version": sys.version, >> "platform": sys.platform, >> "executable": sys.executable, >> "default_encoding": sys.getdefaultencoding(), >> "filesystem_encoding": sys.getfilesystemencoding(), >> "os_name": os.name, >> "os_version": platform.platform(), >> "desktop_path": os.environ.get('DESKTOP_PATH', '') >> }, >> "environment_vars": { >> "PYTHONPATH": os.environ.get('PYTHONPATH', ''), >> "PYTHONHOME": os.environ.get('PYTHONHOME', ''), >> "PATH": os.environ.get('PATH', '') >> }, >> "path_analysis": { >> "desktop_path_exists_in_sys_path": False, >> "desktop_path_position": -1, >> "sys_path": sys.path >> }, >> "module_import_test": {"success": False, "error": ""}, >> "file_operation_test": {"success": False, "error": ""}, >> "site_packages_analysis": [] >> } >> >> # 路径分析 >> desktop_path = diagnostic_data["system_info"]["desktop_path"] >> if desktop_path: >> desktop_abs = os.path.abspath(desktop_path) >> if desktop_abs in [os.path.abspath(p) for p in sys.path]: >> diagnostic_data["path_analysis"]["desktop_path_exists_in_sys_path"] = True >> diagnostic_data["path_analysis"]["desktop_path_position"] = [ >> os.path.abspath(p) for p in sys.path >> ].index(desktop_abs) >> >> # 模块导入测试 >> if desktop_path: >> test_module = os.path.join(desktop_path, "diagnostic_test_module.py") >> try: >> with open(test_module, 'w', encoding='utf-8') as f: >> f.write("def test_function():\n return '诊断测试成功'") >> >> spec = importlib.util.spec_from_file_location("diagnostic_test_module", test_module) >> module = importlib.util.module_from_spec(spec) >> spec.loader.exec_module(module) >> result = module.test_function() >> diagnostic_data["module_import_test"]["success"] = True >> diagnostic_data["module_import_test"]["result"] = result >> except Exception as e: >> diagnostic_data["module_import_test"]["error"] = str(e) >> diagnostic_data["module_import_test"]["traceback"] = traceback.format_exc() >> finally: >> try: >> os.remove(test_module) >> except: >> pass >> >> # 文件操作测试 >> if desktop_path: >> test_file = os.path.join(desktop_path, "diagnostic_test_file.txt") >> try: >> with open(test_file, 'w', encoding='utf-8') as f: >> f.write("Python环境诊断测试文件") >> >> if os.path.exists(test_file): >> diagnostic_data["file_operation_test"]["success"] = True >> os.remove(test_file) >> except Exception as e: >> diagnostic_data["file_operation_test"]["error"] = str(e) >> diagnostic_data["file_operation_test"]["traceback"] = traceback.format_exc() >> >> # site-packages分析 >> for path in sys.path: >> if 'site-packages' in path and os.path.isdir(path): >> dir_info = { >> "path": path, >> "pth_files": [], >> "sitecustomize_exists": os.path.exists(os.path.join(path, "sitecustomize.py")) >> } >> >> try: >> for file in os.listdir(path): >> if file.endswith('.pth'): >> pth_path = os.path.join(path, file) >> with open(pth_path, 'r', encoding='utf-8') as f: >> content = f.read().strip() >> dir_info["pth_files"].append({ >> "name": file, >> "content": content >> }) >> except Exception as e: >> dir_info["error"] = str(e) >> >> diagnostic_data["site_packages_analysis"].append(dir_info) >> >> # 输出JSON格式结果 >> print(json.dumps(diagnostic_data, indent=2, ensure_ascii=False)) >> "@ >> >> $tempScript = Join-Path $env:TEMP "python_diagnostic_$(Get-Date -Format 'yyyyMMdd_HHmmss').py" >> Set-Content -Path $tempScript -Value $testScript -Encoding UTF8 >> >> Write-Host "`n🚀 运行全面环境诊断..." -ForegroundColor Cyan >> try { >> $result = & $pythonExe $tempScript | ConvertFrom-Json >> >> # 显示摘要报告 >> Write-Host "`n=== 诊断报告摘要 ===" -ForegroundColor Green >> Write-Host "Python版本: $($result.system_info.python_version.split()[0])" >> Write-Host "系统平台: $($result.system_info.platform)" >> Write-Host "桌面路径: $($result.system_info.desktop_path)" >> Write-Host "路径存在: $($result.path_analysis.desktop_path_exists_in_sys_path)" >> Write-Host "模块导入: $($result.module_import_test.success)" >> Write-Host "文件操作: $($result.file_operation_test.success)" >> >> if ($Detailed) { >> Write-Host "`n=== 详细诊断数据 ===" -ForegroundColor Yellow >> $result | Format-List | Out-String | Write-Host >> } >> >> return $true >> } catch { >> Write-Host "❌ 诊断执行失败: $_" -ForegroundColor Red >> return $false >> } finally { >> Remove-Item $tempScript -ErrorAction SilentlyContinue >> } >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 5.执行逻辑 PS C:\Users\Administrator\Desktop> param( >> [string]$PythonPath = "E:\Python310", >> [switch]$DiagnoseOnly = $false >> ) PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 执行修复或诊断 PS C:\Users\Administrator\Desktop> if ($DiagnoseOnly) { >> Test-PythonEnvironment -PythonPath $PythonPath -Detailed >> } else { >> if (Repair-PythonEnvironment -PythonPath $PythonPath) { >> Write-Host "`n✅ 修复完成!运行诊断测试..." -ForegroundColor Green >> Test-PythonEnvironment -PythonPath $PythonPath >> } >> } 创建sitecustomize.py: E:\Python310\Lib\site-packages\sitecustomize.py 创建系统级.pth文件: E:\Python310\Lib\site-packages\desktop_path.pth 创建用户级.pth文件: C:\Users\Administrator\AppData\Roaming\Python\Python310\site-packages\desktop_path.pth 创建Python路径文件: E:\Python310\pythonpath.txt ✅ Python环境修复完成 ✅ 修复完成!运行诊断测试... 🚀 运行全面环境诊断... === 诊断报告摘要 === Python版本: 3.10.10 系统平台: win32 桌面路径: C:\Users\Administrator\Desktop 路径存在: False 模块导入: True 文件操作: True True PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 6. 保存脚本 PS C:\Users\Administrator\Desktop> $scriptContent = $MyInvocation.MyCommand.Definition PS C:\Users\Administrator\Desktop> $scriptName = "PythonEnvRepair_Complete_Fix.ps1" PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> @( >> [Environment]::GetFolderPath([Environment+SpecialFolder]::Desktop), >> [Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments), >> "C:\Temp", >> $env:USERPROFILE, >> "C:\Scripts" >> ) | Where-Object { Test-Path $_ } | ForEach-Object { >> $scriptPath = Join-Path $_ $scriptName >> Set-Content -Path $scriptPath -Value $scriptContent -Encoding UTF8 >> Write-Host "脚本已保存到: $scriptPath" -ForegroundColor Cyan >> } 脚本已保存到: C:\Users\Administrator\Desktop\PythonEnvRepair_Complete_Fix.ps1 脚本已保存到: C:\Users\Administrator\Documents\PythonEnvRepair_Complete_Fix.ps1 脚本已保存到: C:\Temp\PythonEnvRepair_Complete_Fix.ps1 脚本已保存到: C:\Users\Administrator\PythonEnvRepair_Complete_Fix.ps1 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 7. 最终提示 PS C:\Users\Administrator\Desktop> Write-Host "`n🔧 后续操作建议:" 🔧 后续操作建议: PS C:\Users\Administrator\Desktop> Write-Host "1. 重启所有Python相关进程" -ForegroundColor Yellow 1. 重启所有Python相关进程 PS C:\Users\Administrator\Desktop> Write-Host "2. 重启终端使环境变量生效" -ForegroundColor Yellow 2. 重启终端使环境变量生效 PS C:\Users\Administrator\Desktop> Write-Host "3. 定期运行诊断: Test-PythonEnvironment -PythonPath '$PythonPath'" -ForegroundColor Cyan 3. 定期运行诊断: Test-PythonEnvironment -PythonPath 'E:\Python310' PS C:\Users\Administrator\Desktop> .\PythonEnvRepair_Complete_Fix.ps1 -PythonPath "E:\Python310" PS C:\Users\Administrator\Desktop> .\PythonEnvRepair_Complete_Fix.ps1 -PythonPath "E:\Python310" -DiagnoseOnly -Detailed PS C:\Users\Administrator\Desktop> Get-Content ~/python_env_fix.log Get-Content : 找不到路径“C:\Users\Administrator\python_env_fix.log”,因为该路径不存在。 所在位置 行:1 字符: 1 + Get-Content ~/python_env_fix.log + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (C:\Users\Admini...hon_env_fix.log:String) [Get-Content], ItemNotFoundEx ception + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand PS C:\Users\Administrator\Desktop> python -c "import sys; print('桌面路径在sys.path中' if r'C:\Users\Administrator\Desktop' in sys.path else '路径未添加')" 路径未添加 PS C:\Users\Administrator\Desktop> # PythonEnvRepair_Centralized.ps1 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 1. 定义集中存储目录(优先E盘,其次C盘) PS C:\Users\Administrator\Desktop> $centralStorage = @("E:\PythonEnvFix", "C:\PythonEnvFix") | Where-Object { >> -not (Test-Path $_) -or (Test-Path $_ -PathType Container) >> } | Select-Object -First 1 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 创建存储目录(如果不存在) PS C:\Users\Administrator\Desktop> if (-not (Test-Path $centralStorage)) { >> New-Item -ItemType Directory -Path $centralStorage -Force | Out-Null >> Write-Host "创建集中存储目录: $centralStorage" -ForegroundColor Cyan >> } 创建集中存储目录: E:\PythonEnvFix PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 2. 设置桌面路径(仅用于Python环境) PS C:\Users\Administrator\Desktop> $desktopPath = [Environment]::GetFolderPath([Environment+SpecialFolder]::Desktop) PS C:\Users\Administrator\Desktop> if (-not (Test-Path $desktopPath)) { >> $desktopPath = Join-Path $centralStorage "Desktop" >> New-Item -ItemType Directory -Path $desktopPath -Force | Out-Null >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 3. 核心修复函数(无桌面文件生成) PS C:\Users\Administrator\Desktop> function global:Repair-PythonEnvironment { >> param( >> [string]$PythonPath = "E:\Python310", >> [switch]$Silent = $false >> ) >> >> # 验证Python安装 >> $pythonExe = Join-Path $PythonPath "python.exe" >> if (-not (Test-Path $pythonExe)) { >> Write-Host "❌ 错误: 找不到python.exe: $pythonExe" -ForegroundColor Red >> return $false >> } >> >> # 创建修复日志目录 >> $logDir = Join-Path $centralStorage "Logs" >> if (-not (Test-Path $logDir)) { >> New-Item -ItemType Directory -Path $logDir -Force | Out-Null >> } >> >> # 生成日志文件路径(集中存储) >> $logFile = Join-Path $logDir "PythonFix_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" >> >> # 创建sitecustomize.py(内存中生成) >> $sitecustomizeContent = @" >> import sys >> import os >> import site >> import logging >> >> # 配置日志(集中存储) >> log_dir = r"$logDir" >> if not os.path.exists(log_dir): >> try: >> os.makedirs(log_dir) >> except: >> log_dir = os.path.expanduser("~") >> >> log_file = os.path.join(log_dir, "python_env_fix.log") >> logging.basicConfig( >> filename=log_file, >> level=logging.INFO, >> format='%(asctime)s - %(levelname)s - %(message)s', >> encoding='utf-8' >> ) >> >> logger = logging.getLogger('PythonEnvFix') >> >> # 添加桌面路径到系统路径 >> desktop_path = r"$desktopPath" >> if desktop_path not in sys.path: >> sys.path.insert(0, desktop_path) >> logger.info(f"添加桌面路径到sys.path: {desktop_path}") >> >> # 添加集中存储目录到路径 >> if r"$centralStorage" not in sys.path: >> sys.path.append(r"$centralStorage") >> logger.info(f"添加集中存储路径: $centralStorage") >> >> # 刷新模块缓存 >> sys.path_importer_cache.clear() >> "@ >> >> # 直接写入Python的site-packages(不生成中间文件) >> $sitePackages = Join-Path $PythonPath "Lib\site-packages" >> $sitecustomizePath = Join-Path $sitePackages "sitecustomize.py" >> Set-Content -Path $sitecustomizePath -Value $sitecustomizeContent -Encoding UTF8 >> >> # 创建.pth文件(直接指向桌面路径) >> $pthPath = Join-Path $sitePackages "desktop_path.pth" >> Set-Content -Path $pthPath -Value $desktopPath -Encoding UTF8 >> >> if (-not $Silent) { >> Write-Host "✅ Python环境修复完成" -ForegroundColor Green >> Write-Host "日志文件: $logFile" -ForegroundColor Cyan >> } >> >> return $true >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 4. 诊断函数(无文件生成) PS C:\Users\Administrator\Desktop> function global:Test-PythonEnvironment { >> param( >> [string]$PythonPath = "E:\Python310" >> ) >> >> $pythonExe = Join-Path $PythonPath "python.exe" >> if (-not (Test-Path $pythonExe)) { >> Write-Host "❌ 错误: 找不到python.exe: $pythonExe" -ForegroundColor Red >> return $false >> } >> >> # 直接在内存中执行诊断 >> $diagnosticScript = @" >> import sys >> import os >> import json >> >> result = { >> "status": "success", >> "desktop_path": r"$desktopPath", >> "in_sys_path": r"$desktopPath" in sys.path, >> "central_storage": r"$centralStorage", >> "central_in_path": r"$centralStorage" in sys.path, >> "sys_path": sys.path >> } >> >> print(json.dumps(result)) >> "@ >> >> # 直接通过命令行执行(不生成文件) >> $diagnosticResult = & $pythonExe -c $diagnosticScript | ConvertFrom-Json >> >> # 显示结果 >> Write-Host "`n=== 环境诊断报告 ===" -ForegroundColor Green >> Write-Host "桌面路径: $($diagnosticResult.desktop_path)" >> Write-Host "在sys.path中: $($diagnosticResult.in_sys_path)" >> Write-Host "集中存储路径: $($diagnosticResult.central_storage)" >> Write-Host "在sys.path中: $($diagnosticResult.central_in_path)" >> >> if ($diagnosticResult.in_sys_path -and $diagnosticResult.central_in_path) { >> Write-Host "✅ 环境状态正常" -ForegroundColor Green >> } else { >> Write-Host "⚠️ 环境需要修复" -ForegroundColor Yellow >> Write-Host "运行命令: Repair-PythonEnvironment -PythonPath '$PythonPath'" -ForegroundColor Cyan >> } >> >> return $true >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 5. 清理函数(删除多余文件) PS C:\Users\Administrator\Desktop> function global:Clean-PythonFixFiles { >> # 删除可能存在的旧脚本 >> $locations = @( >> [Environment]::GetFolderPath([Environment+SpecialFolder]::Desktop), >> [Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments), >> "C:\Temp", >> $env:USERPROFILE >> ) >> >> $patterns = @("*PythonEnvRepair*.ps1", "*PythonEnvFix*.log") >> >> foreach ($location in $locations) { >> if (Test-Path $location) { >> foreach ($pattern in $patterns) { >> Get-ChildItem -Path $location -Filter $pattern -ErrorAction SilentlyContinue | ForEach-Object { >> Remove-Item $_.FullName -Force >> Write-Host "已删除: $($_.FullName)" -ForegroundColor Yellow >> } >> } >> } >> } >> >> Write-Host "✅ 清理完成" -ForegroundColor Green >> } PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 6.执行逻辑 PS C:\Users\Administrator\Desktop> param( >> [string]$PythonPath = "E:\Python310", >> [switch]$CleanOnly = $false >> ) PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 执行清理或修复 PS C:\Users\Administrator\Desktop> if ($CleanOnly) { >> Clean-PythonFixFiles >> } else { >> # 先清理旧文件 >> Clean-PythonFixFiles -ErrorAction SilentlyContinue >> >> # 执行修复 >> if (Repair-PythonEnvironment -PythonPath $PythonPath -Silent) { >> Write-Host "`n✅ 修复完成!运行诊断测试..." -ForegroundColor Green >> Test-PythonEnvironment -PythonPath $PythonPath >> } >> } 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Complete_Fix.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Complete_Fixed.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Final_Complete.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Final_Corrected.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Final_Fix.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Final_Solution.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Full.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Full_Final.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Full_Final_Fixed.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Full_Fixed.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Full_Optimized.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Guaranteed_Fix.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Ultimate_Fix.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Ultimate_Fixed.ps1 已删除: C:\Users\Administrator\Desktop\PythonEnvRepair_Ultimate_Solution.ps1 已删除: C:\Users\Administrator\Documents\PythonEnvRepair_Complete_Fix.ps1 已删除: C:\Temp\PythonEnvRepair_Complete_Fix.ps1 已删除: C:\Temp\PythonEnvRepair_Complete_Fixed.ps1 已删除: C:\Temp\PythonEnvRepair_Final_Complete.ps1 已删除: C:\Temp\PythonEnvRepair_Final_Corrected.ps1 已删除: C:\Temp\PythonEnvRepair_Final_Fix.ps1 已删除: C:\Temp\PythonEnvRepair_Final_Solution.ps1 已删除: C:\Temp\PythonEnvRepair_Full_Final.ps1 已删除: C:\Temp\PythonEnvRepair_Full_Final_Fixed.ps1 已删除: C:\Temp\PythonEnvRepair_Full_Fixed.ps1 已删除: C:\Temp\PythonEnvRepair_Full_Optimized.ps1 已删除: C:\Temp\PythonEnvRepair_Guaranteed_Fix.ps1 已删除: C:\Temp\PythonEnvRepair_Ultimate_Fix.ps1 已删除: C:\Temp\PythonEnvRepair_Ultimate_Fixed.ps1 已删除: C:\Temp\PythonEnvRepair_Ultimate_Solution.ps1 已删除: C:\Users\Administrator\PythonEnvRepair_Complete_Fix.ps1 已删除: C:\Users\Administrator\PythonEnvRepair_Final_Fix.ps1 ✅ 清理完成 ✅ 修复完成!运行诊断测试... File "<string>", line 5 result = { ^ SyntaxError: '{' was never closed === 环境诊断报告 === 桌面路径: 在sys.path中: 集中存储路径: 在sys.path中: ⚠️ 环境需要修复 运行命令: Repair-PythonEnvironment -PythonPath 'E:\Python310' True PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 7. 保存主脚本到集中目录(不在桌面) PS C:\Users\Administrator\Desktop> $scriptPath = Join-Path $centralStorage "PythonEnvRepair_Centralized.ps1" PS C:\Users\Administrator\Desktop> Set-Content -Path $scriptPath -Value $MyInvocation.MyCommand.Definition -Encoding UTF8 PS C:\Users\Administrator\Desktop> Write-Host "主脚本位置: $scriptPath" -ForegroundColor Cyan 主脚本位置: E:\PythonEnvFix\PythonEnvRepair_Centralized.ps1 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 8. 最终提示 PS C:\Users\Administrator\Desktop> Write-Host "`n💻 环境管理命令:" -ForegroundColor Magenta 💻 环境管理命令: PS C:\Users\Administrator\Desktop> Write-Host "1. 修复环境: Repair-PythonEnvironment -PythonPath '$PythonPath'" -ForegroundColor Cyan 1. 修复环境: Repair-PythonEnvironment -PythonPath 'E:\Python310' PS C:\Users\Administrator\Desktop> Write-Host "2. 诊断环境: Test-PythonEnvironment -PythonPath '$PythonPath'" -ForegroundColor Cyan 2. 诊断环境: Test-PythonEnvironment -PythonPath 'E:\Python310' PS C:\Users\Administrator\Desktop> Write-Host "3. 清理文件: Clean-PythonFixFiles" -ForegroundColor Yellow 3. 清理文件: Clean-PythonFixFiles PS C:\Users\Administrator\Desktop> Write-Host "`n所有文件集中在: $centralStorage" -ForegroundColor Green 所有文件集中在: E:\PythonEnvFix PS C:\Users\Administrator\Desktop> .\PythonEnvRepair_Centralized.ps1 -PythonPath "E:\Python310" .\PythonEnvRepair_Centralized.ps1 : 无法将“.\PythonEnvRepair_Centralized.ps1”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径, 请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 + .\PythonEnvRepair_Centralized.ps1 -PythonPath "E:\Python310" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (.\PythonEnvRepair_Centralized.ps1:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException PS C:\Users\Administrator\Desktop> # 修复环境 PS C:\Users\Administrator\Desktop> Repair-PythonEnvironment -PythonPath "E:\Python310" ✅ Python环境修复完成 日志文件: E:\PythonEnvFix\Logs\PythonFix_20250822_225714.log True PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 诊断环境 PS C:\Users\Administrator\Desktop> Test-PythonEnvironment -PythonPath "E:\Python310" File "<string>", line 5 result = { ^ SyntaxError: '{' was never closed === 环境诊断报告 === 桌面路径: 在sys.path中: 集中存储路径: 在sys.path中: ⚠️ 环境需要修复 运行命令: Repair-PythonEnvironment -PythonPath 'E:\Python310' True PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 清理旧文件 PS C:\Users\Administrator\Desktop> Clean-PythonFixFiles ✅ 清理完成 PS C:\Users\Administrator\Desktop> # 立即清理桌面Python相关文件 PS C:\Users\Administrator\Desktop> Get-ChildItem -Path $env:USERPROFILE\Desktop -Filter *PythonEnv* -File | Remove-Item -Force PS C:\Users\Administrator\Desktop> Get-ChildItem -Path $env:USERPROFILE\Desktop -Filter *PythonFix* -File | Remove-Item -Force PS C:\Users\Administrator\Desktop> Write-Host "✅ 桌面已清理" -ForegroundColor Green ✅ 桌面已清理 PS C:\Users\Administrator\Desktop> # 验证桌面路径是否在Python路径中 PS C:\Users\Administrator\Desktop> python -c "import sys; print('✅ 桌面路径在sys.path中' if r'C:\Users\Administrator\Desktop' in sys.path else '❌ 路径未添加')" ❌ 路径未添加 PS C:\Users\Administrator\Desktop> PS C:\Users\Administrator\Desktop> # 检查集中存储路径 PS C:\Users\Administrator\Desktop> python -c "import sys; print(f'集中存储路径: {[p for p in sys.path if p.startswith(\"E:\PythonEnvFix\")][0]}')" File "<string>", line 1 import sys; print(f'集中存储路径: {[p for p in sys.path if p.startswith(" E:\PythonEnvFix\)][0]}') ^ SyntaxError: f-string expression part cannot include a backslash PS C:\Users\Administrator\Desktop>
最新发布
08-23
ERROR: script ‘D:\海康\MVS\Development\Samples\Python\MvImport\cloth_inspection_main.py’ not found还是出现了这个问题 – coding: utf-8 – import sys import os import cv2 import numpy as np import time from PyQt5.QtWidgets import ( QApplication, QMainWindow, QPushButton, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox, QLabel, QFileDialog, QToolBar, QComboBox, QStatusBar, QGroupBox, QSlider, QDockWidget, QProgressDialog, QLineEdit, QRadioButton, QGridLayout, QSpinBox ) from PyQt5.QtCore import QRect, Qt, QSettings, QThread, pyqtSignal from CamOperation_class import CameraOperation sys.path.append(“D:\海康\MVS\Development\Samples\Python\wanzheng.py”) import ctypes from ctypes import cast, POINTER from datetime import datetime import logging import socket import serial import skimage import platform from CameraConstants import * import threading import time import sys import wanzheng from wanzheng import some_function class ManagedThread(threading.Thread): def init(self, *args, **kwargs): super().init(*args, **kwargs) self._stop_event = threading.Event() 设置为非守护线程 self.daemon = False def stop(self): “”“安全停止线程”“” self._stop_event.set() def should_stop(self): “”“检查是否应该停止”“” return self._stop_event.is_set() def worker(): “”“线程工作函数”“” try: while not threading.current_thread().should_stop(): 模拟工作 time.sleep(1) 安全输出 sys.stdout.write(“Working…\n”) except Exception as e: 避免在关闭时使用stderr pass def main(): 创建并启动线程 threads = [] for _ in range(3): t = ManagedThread(target=worker) t.start() threads.append(t) try: # 主程序逻辑 time.sleep(5) finally: # 安全停止所有线程 for t in threads: t.stop() for t in threads: t.join(timeout=2.0) # 设置超时避免无限等待 # 确保所有输出完成 sys.stdout.flush() sys.stderr.flush() 在导入部分添加 from CameraParams_header import ( MV_GIGE_DEVICE, MV_USB_DEVICE, MV_GENTL_CAMERALINK_DEVICE, MV_GENTL_CXP_DEVICE, MV_GENTL_XOF_DEVICE ) ===== 路径修复 ===== def fix_sdk_path(): “”“修复海康SDK的加载路径”“” if getattr(sys, ‘frozen’, False): # 打包模式 base_path = sys.MEIPASS mvimport_path = os.path.join(base_path, “MvImport”) if mvimport_path not in sys.path: sys.path.insert(0, mvimport_path) if sys.platform == ‘win32’: os.environ[‘PATH’] = base_path + os.pathsep + os.environ[‘PATH’] try: ctypes.WinDLL(os.path.join(base_path, “MvCamCtrldll.dll”)) except OSError as e: print(f"核心DLL加载失败: {e}“) sys.exit(1) else: # 开发模式 sys.path.insert(0, os.path.dirname(os.path.abspath(file))) 立即执行路径修复 fix_sdk_path() ===== 正确导入SDK模块 ===== try: from MvImport.MvCameraControl_class import MvCamera print(“成功导入MvCamera类”) from CameraParams_header import * from MvErrorDefine_const import * except ImportError as e: print(f"SDK导入失败: {e}”) sys.exit(1) 配置日志系统 logging.basicConfig( level=logging.DEBUG, format=‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’, handlers=[ logging.FileHandler(“cloth_inspection_debug.log”), logging.StreamHandler() ] ) logging.info(“布料印花检测系统启动”) 全局变量 current_sample_path = “” detection_history = [] isGrabbing = False isOpen = False obj_cam_operation = None frame_monitor_thread = None sensor_monitor_thread = None sensor_controller = None MV_OK = 0 MV_E_CALLORDER = -2147483647 ==================== 传感器通讯模块 ==================== class SensorController: def init(self): self.connected = False self.running = False self.connection = None def connect(self, config): try: if config[‘type’] == ‘serial’: self.connection = serial.Serial( port=config[‘port’], baudrate=config[‘baudrate’], timeout=config.get(‘timeout’, 1.0) ) else: self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.connection.connect((config[‘ip’], config[‘port’])) self.connection.settimeout(config.get(‘timeout’, 1.0)) self.connected = True self.running = True logging.info(f"传感器连接成功: {config}“) return True except Exception as e: logging.error(f"传感器连接失败: {str(e)}”) return False def disconnect(self): if self.connection: try: self.connection.close() except: pass self.connection = None self.connected = False self.running = False logging.info(“传感器已断开”) def read_data(self): if not self.connected: return None return { ‘tension’: np.random.uniform(10.0, 20.0), ‘speed’: np.random.uniform(1.0, 5.0), ‘temperature’: np.random.uniform(20.0, 30.0), ‘humidity’: np.random.uniform(40.0, 60.0) } def wait_for_material(self, delay_seconds=0): if not self.connected: logging.warning(“未连接传感器,跳过等待”) return False logging.info(f"等待布料到达,延迟 {delay_seconds} 秒") start_time = time.time() while time.time() - start_time < delay_seconds: QThread.msleep(100) if not self.running: return False logging.info(“布料已到位,准备拍摄”) return True class SensorMonitorThread(QThread): data_updated = pyqtSignal(dict) def init(self, sensor_controller): super().init() self.sensor_controller = sensor_controller self.running = True def run(self): while self.running: if self.sensor_controller and self.sensor_controller.connected: try: data = self.sensor_controller.read_data() if data: self.data_updated.emit(data) except Exception as e: logging.error(f"传感器数据读取错误: {str(e)}“) QThread.msleep(500) def stop(self): self.running = False self.wait(2000) def wait_for_material(self, delay_seconds): return self.sensor_controller.wait_for_material(delay_seconds) ==================== 相机帧监控线程 ==================== class FrameMonitorThread(QThread): frame_status = pyqtSignal(str) # 用于发送状态消息的信号 def init(self, cam_operation): super().init() self.cam_operation = cam_operation self.running = True self.frame_count = 0 self.last_time = time.time() def run(self): “”“监控相机帧状态的主循环””" while self.running: try: if self.cam_operation and self.cam_operation.is_grabbing: # 获取帧统计信息 frame_info = self.get_frame_info() if frame_info: fps = frame_info.get(‘fps’, 0) dropped = frame_info.get(‘dropped’, 0) status = f"FPS: {fps:.1f} | 丢帧: {dropped}" self.frame_status.emit(status) else: self.frame_status.emit(“取流中…”) else: self.frame_status.emit(“相机未取流”) except Exception as e: self.frame_status.emit(f"监控错误: {str(e)}“) # 每500ms检查一次 QThread.msleep(500) def stop(self): “”“停止监控线程””" self.running = False self.wait(1000) # 等待线程结束 def calculate_fps(self): “”“计算当前帧率”“” current_time = time.time() elapsed = current_time - self.last_time if elapsed > 0: fps = self.frame_count / elapsed self.frame_count = 0 self.last_time = current_time return fps return 0 def get_frame_info(self): “”“获取帧信息”“” try: # 更新帧计数 self.frame_count += 1 # 返回帧信息 return { ‘fps’: self.calculate_fps(), ‘dropped’: 0 # 实际应用中需要从相机获取真实丢帧数 } except Exception as e: logging.error(f"获取帧信息失败: {str(e)}“) return None ==================== 优化后的检测算法 ==================== def enhanced_check_print_quality(sample_image_path, test_image, threshold=0.05, sensor_data=None): if sensor_data: speed_factor = min(1.0 + sensor_data[‘speed’] * 0.1, 1.5) env_factor = 1.0 + abs(sensor_data[‘temperature’] - 25) * 0.01 + abs(sensor_data[‘humidity’] - 50) * 0.005 adjusted_threshold = threshold * speed_factor * env_factor logging.info(f"根据传感器数据调整阈值: 原始={threshold:.4f}, 调整后={adjusted_threshold:.4f}”) else: adjusted_threshold = threshold try: sample_img_data = np.fromfile(sample_image_path, dtype=np.uint8) sample_image = cv2.imdecode(sample_img_data, cv2.IMREAD_GRAYSCALE) if sample_image is None: logging.error(f"无法解码样本图像: {sample_image_path}“) return None, None, None except Exception as e: logging.exception(f"样本图像读取异常: {str(e)}”) return None, None, None if len(test_image.shape) == 3: test_image_gray = cv2.cvtColor(test_image, cv2.COLOR_BGR2GRAY) else: test_image_gray = test_image.copy() sample_image = cv2.GaussianBlur(sample_image, (5, 5), 0) test_image_gray = cv2.GaussianBlur(test_image_gray, (5, 5), 0) try: orb = cv2.ORB_create(nfeatures=200) keypoints1, descriptors1 = orb.detectAndCompute(sample_image, None) keypoints2, descriptors2 = orb.detectAndCompute(test_image_gray, None) if descriptors1 is None or descriptors2 is None: logging.warning(“无法提取特征描述符,跳过配准”) aligned_sample = sample_image else: bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = bf.match(descriptors1, descriptors2) matches = sorted(matches, key=lambda x: x.distance) if len(matches) > 10: src_pts = np.float32([keypoints1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) if H is not None: aligned_sample = cv2.warpPerspective( sample_image, H, (test_image_gray.shape[1], test_image_gray.shape[0]) ) logging.info(“图像配准成功,使用配准后样本”) else: aligned_sample = sample_image logging.warning(“无法计算单应性矩阵,使用原始样本”) else: aligned_sample = sample_image logging.warning(“特征点匹配不足,跳过图像配准”) except Exception as e: logging.error(f"图像配准失败: {str(e)}“) aligned_sample = sample_image try: if aligned_sample.shape != test_image_gray.shape: test_image_gray = cv2.resize(test_image_gray, (aligned_sample.shape[1], aligned_sample.shape[0])) except Exception as e: logging.error(f"图像调整大小失败: {str(e)}”) return None, None, None try: from skimage.metrics import structural_similarity as compare_ssim ssim_score, ssim_diff = compare_ssim( aligned_sample, test_image_gray, full=True, gaussian_weights=True, data_range=255 ) except ImportError: from skimage.measure import compare_ssim ssim_score, ssim_diff = compare_ssim( aligned_sample, test_image_gray, full=True, gaussian_weights=True ) except Exception as e: logging.error(f"SSIM计算失败: {str(e)}“) abs_diff = cv2.absdiff(aligned_sample, test_image_gray) ssim_diff = abs_diff.astype(np.float32) / 255.0 ssim_score = 1.0 - np.mean(ssim_diff) ssim_diff = (1 - ssim_diff) * 255 abs_diff = cv2.absdiff(aligned_sample, test_image_gray) combined_diff = cv2.addWeighted(ssim_diff.astype(np.uint8), 0.7, abs_diff, 0.3, 0) , thresholded = cv2.threshold(combined_diff, 30, 255, cv2.THRESH_BINARY) kernel = np.ones((3, 3), np.uint8) thresholded = cv2.morphologyEx(thresholded, cv2.MORPH_OPEN, kernel) thresholded = cv2.morphologyEx(thresholded, cv2.MORPH_CLOSE, kernel) diff_pixels = np.count_nonzero(thresholded) total_pixels = aligned_sample.size diff_ratio = diff_pixels / total_pixels is_qualified = diff_ratio <= adjusted_threshold marked_image = cv2.cvtColor(test_image_gray, cv2.COLOR_GRAY2BGR) marked_image[thresholded == 255] = [0, 0, 255] labels = skimage.measure.label(thresholded) properties = skimage.measure.regionprops(labels) for prop in properties: if prop.area > 50: y, x = prop.centroid cv2.putText(marked_image, f"Defect", (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 1) return is_qualified, diff_ratio, marked_image ==================== 传感器控制的质量检测流程 ==================== def sensor_controlled_check(): global isGrabbing, obj_cam_operation, current_sample_path, detection_history, sensor_controller logging.info(“质量检测启动”) sensor_data = None if sensor_controller and sensor_controller.connected: sensor_data = sensor_controller.read_data() if not sensor_data: QMessageBox.warning(mainWindow, “传感器警告”, “无法读取传感器数据,将使用默认参数”, QMessageBox.Ok) else: logging.info(“未连接传感器,使用默认参数检测”) check_print_with_sensor(sensor_data) def check_print_with_sensor(sensor_data=None): global isGrabbing, obj_cam_operation, current_sample_path, detection_history logging.info(“检测印花质量按钮按下”) if not isGrabbing: QMessageBox.warning(mainWindow, “错误”, “请先开始取流并捕获图像!”, QMessageBox.Ok) return if not obj_cam_operation: QMessageBox.warning(mainWindow, “错误”, “相机未正确初始化!”, QMessageBox.Ok) return if not current_sample_path or not os.path.exists(current_sample_path): QMessageBox.warning(mainWindow, “错误”, “请先设置有效的标准样本图像!”, QMessageBox.Ok) return progress = QProgressDialog(“正在检测…”, “取消”, 0, 100, mainWindow) progress.setWindowModality(Qt.WindowModal) progress.setValue(10) try: test_image = obj_cam_operation.get_current_frame() progress.setValue(30) if test_image is None: QMessageBox.warning(mainWindow, “错误”, “无法获取当前帧图像!”, QMessageBox.Ok) return diff_threshold = mainWindow.sliderDiffThreshold.value() / 100.0 logging.info(f"使用差异度阈值: {diff_threshold}“) progress.setValue(50) is_qualified, diff_ratio, marked_image = enhanced_check_print_quality( current_sample_path, test_image, threshold=diff_threshold, sensor_data=sensor_data ) progress.setValue(70) if is_qualified is None: QMessageBox.critical(mainWindow, “检测错误”, “检测失败,请检查日志”, QMessageBox.Ok) return logging.info(f"检测结果: 合格={is_qualified}, 差异={diff_ratio}”) progress.setValue(90) update_diff_display(diff_ratio, is_qualified) result_text = f"印花是否合格: {‘合格’ if is_qualified else ‘不合格’}\n差异占比: {diff_ratio100:.2f}%\n阈值: {diff_threshold100:.2f}%" QMessageBox.information(mainWindow, “检测结果”, result_text, QMessageBox.Ok) if marked_image is not None: cv2.imshow(“缺陷标记结果”, marked_image) cv2.waitKey(0) cv2.destroyAllWindows() detection_result = { ‘timestamp’: datetime.now(), ‘qualified’: is_qualified, ‘diff_ratio’: diff_ratio, ‘threshold’: diff_threshold, ‘sensor_data’: sensor_data if sensor_data else {} } detection_history.append(detection_result) update_history_display() progress.setValue(100) except Exception as e: logging.exception(“印花检测失败”) QMessageBox.critical(mainWindow, “检测错误”, f"检测过程中发生错误: {str(e)}“, QMessageBox.Ok) finally: progress.close() def update_diff_display(diff_ratio, is_qualified): mainWindow.lblCurrentDiff.setText(f"当前差异度: {diff_ratio*100:.2f}%”) if is_qualified: mainWindow.lblDiffStatus.setText(“状态: 合格”) mainWindow.lblDiffStatus.setStyleSheet(“color: green; font-size: 12px;”) else: mainWindow.lblDiffStatus.setText(“状态: 不合格”) mainWindow.lblDiffStatus.setStyleSheet(“color: red; font-size: 12px;”) def update_diff_threshold(value): mainWindow.lblDiffValue.setText(f"{value}%“) def save_sample_image(): global isGrabbing, obj_cam_operation, current_sample_path if not isGrabbing: QMessageBox.warning(mainWindow, “错误”, “请先开始取流并捕获图像!”, QMessageBox.Ok) return # 检查是否有可用帧 if not obj_cam_operation.is_frame_available(): QMessageBox.warning(mainWindow, “无有效图像”, “未捕获到有效图像,请检查相机状态!”, QMessageBox.Ok) return settings = QSettings(“ClothInspection”, “CameraApp”) last_dir = settings.value(“last_save_dir”, os.path.join(os.getcwd(), “captures”)) timestamp = datetime.now().strftime(”%Y%m%d%H%M%S”) default_filename = f"sample" file_path, selected_filter = QFileDialog.getSaveFileName( mainWindow, “保存标准样本图像”, os.path.join(last_dir, default_filename), “BMP Files (.bmp);;PNG Files (.png);;JPEG Files (.jpg);;所有文件 ()”, options=QFileDialog.DontUseNativeDialog ) if not file_path: return file_extension = os.path.splitext(file_path)[1].lower() if not file_extension: if “BMP” in selected_filter: file_path += “.bmp” elif “PNG” in selected_filter: file_path += “.png” elif “JPEG” in selected_filter or “JPG” in selected_filter: file_path += “.jpg” else: file_path += “.bmp” file_extension = os.path.splitext(file_path)[1].lower() format_mapping = {“.bmp”: “bmp”, “.png”: “png”, “.jpg”: “jpg”, “.jpeg”: “jpg”} save_format = format_mapping.get(file_extension) if not save_format: QMessageBox.warning(mainWindow, “错误”, “不支持的文件格式!”, QMessageBox.Ok) return directory = os.path.dirname(file_path) if directory and not os.path.exists(directory): try: os.makedirs(directory, exist_ok=True) except OSError as e: QMessageBox.critical(mainWindow, “目录创建错误”, f"无法创建目录 {directory}: {str(e)}“, QMessageBox.Ok) return try: ret = obj_cam_operation.save_image(file_path, save_format) if ret != MV_OK: strError = f"保存样本图像失败: {hex(ret)}” QMessageBox.warning(mainWindow, “错误”, strError, QMessageBox.Ok) else: QMessageBox.information(mainWindow, “成功”, f"标准样本已保存至:\n{file_path}“, QMessageBox.Ok) current_sample_path = file_path update_sample_display() settings.setValue(“last_save_dir”, os.path.dirname(file_path)) except Exception as e: QMessageBox.critical(mainWindow, “异常错误”, f"保存图像时发生错误: {str(e)}”, QMessageBox.Ok) def preview_sample(): global current_sample_path if not current_sample_path or not os.path.exists(current_sample_path): QMessageBox.warning(mainWindow, “错误”, “请先设置有效的标准样本图像!”, QMessageBox.Ok) return try: img_data = np.fromfile(current_sample_path, dtype=np.uint8) sample_img = cv2.imdecode(img_data, cv2.IMREAD_COLOR) if sample_img is None: raise Exception(“无法加载图像”) cv2.imshow(“标准样本预览”, sample_img) cv2.waitKey(0) cv2.destroyAllWindows() except Exception as e: QMessageBox.warning(mainWindow, “错误”, f"预览样本失败: {str(e)}“, QMessageBox.Ok) def update_sample_display(): global current_sample_path if current_sample_path: mainWindow.lblSamplePath.setText(f"当前样本: {os.path.basename(current_sample_path)}”) mainWindow.lblSamplePath.setToolTip(current_sample_path) mainWindow.bnPreviewSample.setEnabled(True) else: mainWindow.lblSamplePath.setText(“当前样本: 未设置样本”) mainWindow.bnPreviewSample.setEnabled(False) def update_history_display(): global detection_history mainWindow.cbHistory.clear() for i, result in enumerate(detection_history[-10:]): timestamp = result[‘timestamp’].strftime(“%H:%M:%S”) status = “合格” if result[‘qualified’] else “不合格” ratio = f"{result[‘diff_ratio’]*100:.2f}%" mainWindow.cbHistory.addItem(f"[极客{timestamp}] {status} - 差异: {ratio}“) def TxtWrapBy(start_str, end, all): start = all.find(start_str) if start >= 0: start += len(start_str) end = all.find(end, start) if end >= 0: return all[start:end].strip() def ToHexStr(num): if not isinstance(num, int): try: num = int(num) except: return f”<非整数:{type(num)}>" chaDic = {10: ‘a’, 11: ‘b’, 12: ‘c’, 13: ‘d’, 14: ‘e’, 15: ‘f’} hexStr = “” if num < 0: num = num + 2 ** 32 while num >= 16: digit = num % 16 hexStr = chaDic.get(digit, str(digit)) + hexStr num //= 16 hexStr = chaDic.get(num, str(num)) + hexStr return “0x” + hexStr def decoding_char(c_ubyte_value): c_char_p_value = ctypes.cast(c_ubyte_value, ctypes.c_char_p) try: decode_str = c_char_p_value.value.decode(‘gbk’) except UnicodeDecodeError: decode_str = str(c_char_p_value.value) return decode_str def enum_devices(): global deviceList, obj_cam_operation 使用正确的常量方式 n_layer_type = ( MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICE | MV_GENTL_CXP_DEVICE | MV_GENTL_XOF_DEVICE ) 正确创建设备列表 deviceList = MV_CC_DEVICE_INFO_LIST() # 调用枚举函数 ret = MvCamera.MV_CC_EnumDevices(n_layer_type, deviceList) if ret != 0: strError = “Enum devices fail! ret = :” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) return ret if deviceList.nDeviceNum == 0: QMessageBox.warning(mainWindow, “Info”, “Find no device”, QMessageBox.Ok) return ret print(f"Find {deviceList.nDeviceNum} devices!“) # 处理设备信息 devList = [] for i in range(0, deviceList.nDeviceNum): # 获取设备信息指针 device_info = deviceList.pDeviceInfo[i] # 转换为正确的结构体类型 mvcc_dev_info = cast(device_info, POINTER(MV_CC_DEVICE_INFO)).contents # 根据设备类型提取信息 - 关键修复:使用正确的结构体名称 if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE: # 处理GigE设备信息 - 使用正确的stGigEInfo try: # 尝试访问新版SDK的结构体 st_gige_info = mvcc_dev_info.SpecialInfo.stGigEInfo except AttributeError: try: # 尝试访问旧版SDK的结构体 st_gige_info = mvcc_dev_info.SpecialInfo.stGEInfo except AttributeError: # 如果两种结构体都不存在,使用默认值 devList.append(f”[{i}]GigE: Unknown Device") continue user_defined_name = decoding_char(st_gige_info.chUserDefinedName) model_name = decoding_char(st_gige_info.chModelName) nip1 = ((st_gige_info.nCurrentIp & 0xff000000) >> 24) nip2 = ((st_gige_info.nCurrentIp & 0x00ff0000) >> 16) nip3 = ((st_gige_info.nCurrentIp & 0x0000ff00) >> 8) nip4 = (st_gige_info.nCurrentIp & 0x000000ff) devList.append(f"[{i}]GigE: {user_defined_name} {model_name}({nip1}.{nip2}.{nip3}.{nip4})“) elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE: # 处理USB设备信息 try: st_usb_info = mvcc_dev_info.SpecialInfo.stUsb3VInfo except AttributeError: try: st_usb_info = mvcc_dev_info.SpecialInfo.stUsbInfo except AttributeError: devList.append(f”[{i}]USB: Unknown Device") continue user_defined_name = decoding_char(st_usb_info.chUserDefinedName) model_name = decoding_char(st_usb_info.chModelName) strSerialNumber = “” for per in st_usb_info.chSerialNumber: if per == 0: break strSerialNumber = strSerialNumber + chr(per) devList.append(f"[{i}]USB: {user_defined_name} {model_name}({strSerialNumber})“) else: # 处理其他类型设备 devList.append(f”[{i}]Unknown Device Type: {mvcc_dev_info.nTLayerType}“) # 更新UI mainWindow.ComboDevices.clear() mainWindow.ComboDevices.addItems(devList) mainWindow.ComboDevices.setCurrentIndex(0) # 更新状态栏 mainWindow.statusBar().showMessage(f"找到 {deviceList.nDeviceNum} 个设备”, 3000) return MV_OK ===== 关键改进:相机操作函数 ===== def open_device(): global deviceList, nSelCamIndex, obj_cam_operation, isOpen, frame_monitor_thread, mainWindow if isOpen: QMessageBox.warning(mainWindow, “Error”, ‘相机已打开!’, QMessageBox.Ok) return MV_E_CALLORDER nSelCamIndex = mainWindow.ComboDevices.currentIndex() if nSelCamIndex < 0: QMessageBox.warning(mainWindow, “Error”, ‘请选择相机!’, QMessageBox.Ok) return MV_E_CALLORDER # 创建相机控制对象 cam = MvCamera() # 初始化相机操作对象 - 确保传入有效的相机对象 obj_cam_operation = CameraOperation(cam, deviceList, nSelCamIndex) ret = obj_cam_operation.open_device() if 0 != ret: strError = “打开设备失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) isOpen = False else: set_continue_mode() get_param() isOpen = True enable_controls() # 创建并启动帧监控线程 frame_monitor_thread = FrameMonitorThread(obj_cam_operation) frame_monitor_thread.frame_status.connect(mainWindow.statusBar().showMessage) frame_monitor_thread.start() def start_grabbing(): global obj_cam_operation, isGrabbing 关键改进:添加相机状态检查 if not obj_cam_operation or not hasattr(obj_cam_operation, ‘cam’) or not obj_cam_operation.cam: QMessageBox.warning(mainWindow, “Error”, “相机对象未正确初始化”, QMessageBox.Ok) return ret = obj_cam_operation.start_grabbing(mainWindow.widgetDisplay.winId()) if ret != 0: strError = “开始取流失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) else: isGrabbing = True enable_controls() # 等待第一帧到达 QThread.msleep(500) if not obj_cam_operation.is_frame_available(): QMessageBox.warning(mainWindow, “警告”, “开始取流后未接收到帧,请检查相机连接!”, QMessageBox.Ok) def stop_grabbing(): global obj_cam_operation, isGrabbing 关键改进:添加相机状态检查 if not obj_cam_operation or not hasattr(obj_cam_operation, ‘cam’) or not obj_cam_operation.cam: QMessageBox.warning(mainWindow, “Error”, “相机对象未正确初始化”, QMessageBox.Ok) return 关键改进:添加连接状态检查 if not hasattr(obj_cam_operation, ‘connected’) or not obj_cam_operation.connected: QMessageBox.warning(mainWindow, “Error”, “相机未连接”, QMessageBox.Ok) return ret = obj_cam_operation.Stop_grabbing() if ret != 0: strError = “停止取流失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) else: isGrabbing = False enable_controls() def close_device(): global isOpen, isGrabbing, obj_cam_operation, frame_monitor_thread if frame_monitor_thread and frame_monitor_thread.isRunning(): frame_monitor_thread.stop() frame_monitor_thread.wait(2000) if isOpen and obj_cam_operation: 关键改进:确保相机对象存在 if hasattr(obj_cam_operation, ‘cam’) and obj_cam_operation.cam: obj_cam_operation.close_device() isOpen = False isGrabbing = False enable_controls() def set_continue_mode(): 关键改进:添加相机状态检查 if not obj_cam_operation or not hasattr(obj_cam_operation, ‘cam’) or not obj_cam_operation.cam: return ret = obj_cam_operation.set_trigger_mode(False) if ret != 0: strError = “设置连续模式失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) else: mainWindow.radioContinueMode.setChecked(True) mainWindow.radioTriggerMode.setChecked(False) mainWindow.bnSoftwareTrigger.setEnabled(False) def set_software_trigger_mode(): 关键改进:添加相机状态检查 if not obj_cam_operation or not hasattr(obj_cam_operation, ‘cam’) or not obj_cam_operation.cam: return ret = obj_cam_operation.set_trigger_mode(True) if ret != 0: strError = “设置触发模式失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) else: mainWindow.radioContinueMode.setChecked(False) mainWindow.radioTriggerMode.setChecked(True) mainWindow.bnSoftwareTrigger.setEnabled(isGrabbing) def trigger_once(): 关键改进:添加相机状态检查 if not obj_cam_operation or not hasattr(obj_cam_operation, ‘cam’) or not obj_cam_operation.cam: return ret = obj_cam_operation.trigger_once() if ret != 0: strError = “软触发失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) def save_sample_image(): global isGrabbing, obj_cam_operation, current_sample_path if not isGrabbing: QMessageBox.warning(mainWindow, “错误”, “请先开始取流并捕获图像!”, QMessageBox.Ok) return # 尝试捕获当前帧 frame = obj_cam_operation.capture_frame() if frame is None: QMessageBox.warning(mainWindow, “无有效图像”, “未捕获到有效图像,请检查相机状态!”, QMessageBox.Ok) return # 确保图像有效 if frame.size == 0 or frame.shape[0] == 0 or frame.shape[1] == 0: QMessageBox.warning(mainWindow, “无效图像”, “捕获的图像无效,请检查相机设置!”, QMessageBox.Ok) return settings = QSettings(“ClothInspection”, “CameraApp”) last_dir = settings.value(“last_save_dir”, os.path.join(os.getcwd(), “captures”)) timestamp = datetime.now().strftime(“%Y%m%d_%H%M%S”) default_filename = f"sample_{timestamp}" file_path, selected_filter = QFileDialog.getSaveFileName( mainWindow, “保存标准样本图像”, os.path.join(last_dir, default_filename), “BMP Files (.bmp);;PNG Files (.png);;JPEG Files (.jpg);;所有文件 ()”, options=QFileDialog.DontUseNativeDialog ) if not file_path: return # 确保文件扩展名正确 file_extension = os.path.splitext(file_path)[1].lower() if not file_extension: if “BMP” in selected_filter: file_path += “.bmp” elif “PNG” in selected_filter: file_path += “.png” elif “JPEG” in selected_filter or “JPG” in selected_filter: file_path += “.jpg” else: file_path += “.bmp” file_extension = os.path.splitext(file_path)[1].lower() # 创建目录(如果不存在) directory = os.path.dirname(file_path) if directory and not os.path.exists(directory): try: os.makedirs(directory, exist_ok=True) except OSError as e: QMessageBox.critical(mainWindow, “目录创建错误”, f"无法创建目录 {directory}: {str(e)}“, QMessageBox.Ok) return # 保存图像 try: # 使用OpenCV保存图像 if not cv2.imwrite(file_path, frame): raise Exception(“OpenCV保存失败”) # 更新状态 current_sample_path = file_path update_sample_display() settings.setValue(“last_save_dir”, os.path.dirname(file_path)) # 显示成功消息 QMessageBox.information(mainWindow, “成功”, f"标准样本已保存至:\n{file_path}”, QMessageBox.Ok) # 可选:自动预览样本 preview_sample() except Exception as e: logging.error(f"保存图像失败: {str(e)}“) QMessageBox.critical(mainWindow, “保存错误”, f"保存图像时发生错误:\n{str(e)}”, QMessageBox.Ok) def preview_sample(): global current_sample_path if not current_sample_path or not os.path.exists(current_sample_path): QMessageBox.warning(mainWindow, “错误”, “请先设置有效的标准样本图像!”, QMessageBox.Ok) return try: # 直接使用OpenCV加载图像 sample_img = cv2.imread(current_sample_path) if sample_img is None: raise Exception(“无法加载图像”) # 显示图像 cv2.imshow(“标准样本预览”, sample_img) cv2.waitKey(0) cv2.destroyAllWindows() except Exception as e: QMessageBox.warning(mainWindow, “错误”, f"预览样本失败: {str(e)}", QMessageBox.Ok) def start_grabbing(): global obj_cam_operation, isGrabbing ret = obj_cam_operation.start_grabbing(mainWindow.widgetDisplay.winId()) if ret != 0: strError = “开始取流失败 ret:” + ToHexStr(ret) QMessageBox.warning(mainWindow, “Error”, strError, QMessageBox.Ok) else: isGrabbing = True enable_controls() 等待第一帧到达 QThread.msleep(500) if not obj_cam_operation.is_frame_available(): QMessageBox.warning(mainWindow, “警告”, “开始取流后未接收到帧,请检查相机连接!”, QMessageBox.Ok) def is_float(str): try: float(str) return True except ValueError: return False def get_param(): try: ret = obj_cam_operation.get_parameters() if ret != MV_OK: strError = “获取参数失败,错误码: " + ToHexStr(ret) QMessageBox.warning(mainWindow, “错误”, strError, QMessageBox.Ok) else: mainWindow.edtExposureTime.setText(”{0:.2f}“.format(obj_cam_operation.exposure_time)) mainWindow.edtGain.setText(”{0:.2f}“.format(obj_cam_operation.gain)) mainWindow.edtFrameRate.setText(”{0:.2f}“.format(obj_cam_operation.frame_rate)) except Exception as e: error_msg = f"获取参数时发生错误: {str(e)}” QMessageBox.critical(mainWindow, “严重错误”, error_msg, QMessageBox.Ok) def set_param(): frame_rate = mainWindow.edtFrameRate.text() exposure = mainWindow.edtExposureTime.text() gain = mainWindow.edtGain.text() if not (is_float(frame_rate) and is_float(exposure) and is_float(gain)): strError = “设置参数失败: 参数必须是有效的浮点数” QMessageBox.warning(mainWindow, “错误”, strError, QMessageBox.Ok) return MV_E_PARAMETER try: ret = obj_cam_operation.set_param( frame_rate=float(frame_rate), exposure_time=float(exposure), gain=float(gain) ) if ret != MV_OK: strError = “设置参数失败,错误码: " + ToHexStr(ret) QMessageBox.warning(mainWindow, “错误”, strError, QMessageBox.Ok) except Exception as e: error_msg = f"设置参数时发生错误: {str(e)}” QMessageBox.critical(mainWindow, “严重错误”, error_msg, QMessageBox.Ok) def enable_controls(): global isGrabbing, isOpen mainWindow.groupGrab.setEnabled(isOpen) mainWindow.paramgroup.setEnabled(isOpen) mainWindow.bnOpen.setEnabled(not isOpen) mainWindow.bnClose.setEnabled(isOpen) mainWindow.bnStart.setEnabled(isOpen and (not isGrabbing)) mainWindow.bnStop.setEnabled(isOpen and isGrabbing) mainWindow.bnSoftwareTrigger.setEnabled(isGrabbing and mainWindow.radioTriggerMode.isChecked()) mainWindow.bnSaveImage.setEnabled(isOpen and isGrabbing) mainWindow.bnCheckPrint.setEnabled(isOpen and isGrabbing) mainWindow.bnSaveSample.setEnabled(isOpen and isGrabbing) mainWindow.bnPreviewSample.setEnabled(bool(current_sample_path)) def update_sensor_display(data): if not data: return text = (f"张力: {data[‘tension’]:.2f}N | " f"速度: {data[‘speed’]:.2f}m/s | " f"温度: {data[‘temperature’]:.1f}°C | " f"湿度: {data[‘humidity’]:.1f}%") mainWindow.lblSensorData.setText(text) def connect_sensor(): global sensor_monitor_thread, sensor_controller sensor_type = mainWindow.cbSensorType.currentText() if sensor_controller is None: sensor_controller = SensorController() if sensor_type == “串口”: config = { ‘type’: ‘serial’, ‘port’: mainWindow.cbComPort.currentText(), ‘baudrate’: int(mainWindow.cbBaudrate.currentText()), ‘timeout’: 1.0 } else: config = { ‘type’: ‘ethernet’, ‘ip’: mainWindow.edtIP.text(), ‘port’: int(mainWindow.edtPort.text()), ‘timeout’: 1.0 } if sensor_controller.connect(config): mainWindow.bnConnectSensor.setEnabled(False) mainWindow.bnDisconnectSensor.setEnabled(True) sensor_monitor_thread = SensorMonitorThread(sensor_controller) sensor_monitor_thread.data_updated.connect(update_sensor_display) sensor_monitor_thread.start() def disconnect_sensor(): global sensor_monitor_thread if sensor_controller: sensor_controller.disconnect() mainWindow.bnConnectSensor.setEnabled(True) mainWindow.bnDisconnectSensor.setEnabled(False) if sensor_monitor_thread and sensor_monitor_thread.isRunning(): sensor_monitor_thread.stop() sensor_monitor_thread.wait(2000) sensor_monitor_thread = None mainWindow.lblSensorData.setText(“传感器数据: 未连接”) def update_sensor_ui(index): mainWindow.serialGroup.setVisible(index == 0) mainWindow.ethernetGroup.setVisible(index == 1) class MainWindow(QMainWindow): def init(self): super().init() self.setWindowTitle(“布料印花检测系统”) self.resize(1200, 800) central_widget = QWidget() self.setCentralWidget(central_widget) main_layout = QVBoxLayout(central_widget) 设备枚举区域 device_layout = QHBoxLayout() self.ComboDevices = QComboBox() self.bnEnum = QPushButton(“枚举设备”) self.bnOpen = QPushButton(“打开设备”) self.bnClose = QPushButton(“关闭设备”) device_layout.addWidget(self.ComboDevices) device_layout.addWidget(self.bnEnum) device_layout.addWidget(self.bnOpen) device_layout.addWidget(self.bnClose) main_layout.addLayout(device_layout) # 取流控制组 self.groupGrab = QGroupBox(“取流控制”) grab_layout = QHBoxLayout(self.groupGrab) self.bnStart = QPushButton(“开始取流”) self.bnStop = QPushButton(“停止取流”) self.radioContinueMode = QRadioButton(“连续模式”) self.radioTriggerMode = QRadioButton(“触发模式”) self.bnSoftwareTrigger = QPushButton(“软触发”) grab_layout.addWidget(self.bnStart) grab_layout.addWidget(self.bnStop) grab_layout.addWidget(self.radioContinueMode) grab_layout.addWidget(self.radioTriggerMode) grab_layout.addWidget(self.bnSoftwareTrigger) main_layout.addWidget(self.groupGrab) # 参数设置组 self.paramgroup = QGroupBox(“相机参数”) param_layout = QGridLayout(self.paramgroup) self.edtExposureTime = QLineEdit() self.edtGain = QLineEdit() self.edtFrameRate = QLineEdit() self.bnGetParam = QPushButton(“获取参数”) self.bnSetParam = QPushButton(“设置参数”) self.bnSaveImage = QPushButton(“保存图像”) param_layout.addWidget(QLabel(“曝光时间:”), 0, 0) param_layout.addWidget(self.edtExposureTime, 0, 1) param_layout.addWidget(self.bnGetParam, 0, 2) param_layout.addWidget(QLabel(“增益:”), 1, 0) param_layout.addWidget(self.edtGain, 1, 1) param_layout.addWidget(self.bnSetParam, 1, 2) param_layout.addWidget(QLabel(“帧率:”), 2, 0) param_layout.addWidget(self.edtFrameRate, 2, 1) param_layout.addWidget(self.bnSaveImage, 2, 2) main_layout.addWidget(self.paramgroup) # 图像显示区域 self.widgetDisplay = QLabel() self.widgetDisplay.setMinimumSize(640, 480) self.widgetDisplay.setStyleSheet(“background-color: black;”) self.widgetDisplay.setAlignment(Qt.AlignCenter) self.widgetDisplay.setText(“相机预览区域”) main_layout.addWidget(self.widgetDisplay, 1) # 状态栏 #self.statusBar = QStatusBar() #self.setStatusBar(self.statusBar) # 创建自定义UI组件 self.setup_custom_ui() def setup_custom_ui(self): # 工具栏 toolbar = self.addToolBar(“检测工具”) self.bnCheckPrint = QPushButton(“检测印花质量”) self.bnSaveSample = QPushButton(“保存标准样本”) self.bnPreviewSample = QPushButton(“预览样本”) self.cbHistory = QComboBox() self.cbHistory.setMinimumWidth(300) toolbar.addWidget(self.bnCheckPrint) toolbar.addWidget(self.bnSaveSample) toolbar.addWidget(self.bnPreviewSample) toolbar.addWidget(QLabel(“历史记录:”)) toolbar.addWidget(self.cbHistory) # 状态栏样本路径 self.lblSamplePath = QLabel(“当前样本: 未设置样本”) self.statusBar().addPermanentWidget(self.lblSamplePath) # 右侧面板 right_panel = QWidget() right_layout = QVBoxLayout(right_panel) right_layout.setContentsMargins(10, 10, 10, 10) # 差异度调整组 diff_group = QGroupBox(“差异度调整”) diff_layout = QVBoxLayout(diff_group) self.lblDiffThreshold = QLabel(“差异度阈值 (0-100%)😊 self.sliderDiffThreshold = QSlider(Qt.Horizontal) self.sliderDiffThreshold.setRange(0, 100) self.sliderDiffThreshold.setValue(5) self.lblDiffValue = QLabel(“5%”) self.lblCurrentDiff = QLabel(“当前差异度: -”) self.lblCurrentDiff.setStyleSheet(“font-size: 14px; font-weight: bold;”) self.lblDiffStatus = QLabel(“状态: 未检测”) self.lblDiffStatus.setStyleSheet(“font-size: 12px;”) diff_layout.addWidget(self.lblDiffThreshold) diff_layout.addWidget(self.sliderDiffThreshold) diff_layout.addWidget(self.lblDiffValue) diff_layout.addWidget(self.lblCurrentDiff) diff_layout.addWidget(self.lblDiffStatus) right_layout.addWidget(diff_group) # 传感器控制面板 sensor_panel = QGroupBox(“传感器控制”) sensor_layout = QVBoxLayout(sensor_panel) sensor_type_layout = QHBoxLayout() self.lblSensorType = QLabel(“传感器类型:”) self.cbSensorType = QComboBox() self.cbSensorType.addItems([“串口”, “以太网”]) sensor_type_layout.addWidget(self.lblSensorType) sensor_type_layout.addWidget(self.cbSensorType) sensor_layout.addLayout(sensor_type_layout) # 串口参数 self.serialGroup = QGroupBox(“串口参数”) serial_layout = QVBoxLayout(self.serialGroup) self.lblComPort = QLabel(“端口:”) self.cbComPort = QComboBox() if platform.system() == ‘Windows’: ports = [f"COM{i}” for i in range(1, 21)] else: ports = [f"/dev/ttyS{i}" for i in range(0, 4)] + [f"/dev/ttyUSB{i}" for i in range(0, 4)] self.cbComPort.addItems(ports) self.lblBaudrate = QLabel(“波特率:”) self.cbBaudrate = QComboBox() self.cbBaudrate.addItems([“96000”, “19200”, “38400”, “57600”, “115200”]) self.cbBaudrate.setCurrentText(“115200”) serial_layout.addWidget(self.lblComPort) serial_layout.addWidget(self.cbComPort) serial_layout.addWidget(self.lblBaudrate) serial_layout.addWidget(self.cbBaudrate) sensor_layout.addWidget(self.serialGroup) # 以太网参数 self.ethernetGroup = QGroupBox(“以太网参数”) ethernet_layout = QVBoxLayout(self.ethernetGroup) self.lblIP = QLabel(“IP地址:”) self.edtIP = QLineEdit(“192.168.1.100”) self.lblPort = QLabel(“端口:”) self.edtPort = QLineEdit(“502”) ethernet_layout.addWidget(self.lblIP) ethernet_layout.addWidget(self.edtIP) ethernet_layout.addWidget(self.lblPort) ethernet_layout.addWidget(self.edtPort) sensor_layout.addWidget(self.ethernetGroup) # 连接按钮 self.bnConnectSensor = QPushButton(“连接传感器”) self.bnDisconnectSensor = QPushButton(“断开传感器”) self.bnDisconnectSensor.setEnabled(False) sensor_layout.addWidget(self.bnConnectSensor) sensor_layout.addWidget(self.bnDisconnectSensor) # 延迟设置 delay_layout = QHBoxLayout() self.lblDelay = QLabel("触发延迟(秒)😊 self.spinDelay = QSpinBox() self.spinDelay.setRange(0, 60) self.spinDelay.setValue(0) self.spinDelay.setToolTip(“传感器检测到布料后延迟拍摄的时间”) delay_layout.addWidget(self.lblDelay) delay_layout.addWidget(self.spinDelay) sensor_layout.addLayout(delay_layout) # 传感器数据 self.lblSensorData = QLabel(“传感器数据: 未连接”) self.lblSensorData.setStyleSheet(“font-size: 10pt;”) sensor_layout.addWidget(self.lblSensorData) right_layout.addWidget(sensor_panel) right_layout.addStretch(1) # 停靠窗口 dock = QDockWidget(“检测控制面板”, self) dock.setWidget(right_panel) dock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self.addDockWidget(Qt.RightDockWidgetArea, dock) def closeEvent(self, event): logging.info(“主窗口关闭,执行清理…”) close_device() disconnect_sensor() event.accept() if name == “main”: app = QApplication(sys.argv) mainWindow = MainWindow() 信号连接 mainWindow.cbSensorType.currentIndexChanged.connect(update_sensor_ui) update_sensor_ui(0) mainWindow.bnConnectSensor.clicked.connect(connect_sensor) mainWindow.bnDisconnectSensor.clicked.connect(disconnect_sensor) mainWindow.sliderDiffThreshold.valueChanged.connect(update_diff_threshold) mainWindow.bnCheckPrint.clicked.connect(sensor_controlled_check) mainWindow.bnSaveSample.clicked.connect(save_sample_image) mainWindow.bnPreviewSample.clicked.connect(preview_sample) mainWindow.bnEnum.clicked.connect(enum_devices) mainWindow.bnOpen.clicked.connect(open_device) mainWindow.bnClose.clicked.connect(close_device) mainWindow.bnStart.clicked.connect(start_grabbing) mainWindow.bnStop.clicked.connect(stop_grabbing) mainWindow.bnSoftwareTrigger.clicked.connect(trigger_once) mainWindow.radioTriggerMode.clicked.connect(set_software_trigger_mode) mainWindow.radioContinueMode.clicked.connect(set_continue_mode) mainWindow.bnGetParam.clicked.connect(get_param) mainWindow.bnSetParam.clicked.connect(set_param) mainWindow.bnSaveImage.clicked.connect(save_sample_image) main() mainWindow.show() app.exec_() close_device() disconnect_sensor() sys.exit() 这个是wanzheng.py的代码
07-12
修改用户指定的代码问题Traceback (most recent call last): File "C:\Users\Administrator\Desktop\project\数字模型生成器.py", line 188, in <module> from modules.input_analysis import InputAnalyzer, InputAnalysisModule File "C:\Users\Administrator\Desktop\project\modules\__init__.py", line 48, in <module> InputAnalysisModule: ModuleType = _import_class('input_analysis', 'InputAnalysisModule') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\Administrator\Desktop\project\modules\__init__.py", line 40, in _import_class module = __import__(f".{module_name}", fromlist=[class_name], level=1) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ KeyError: "'__name__' not in globals"代码#!/usr/bin/env python3 # -*- coding: utf-8 -*- # modules/__init__.py """ 分析模块包初始化文件 功能: 1. 集中管理模块暴露的公共接口 2. 控制子模块导入顺序 3. 提供模块版本管理 """ import sys from pathlib import Path from typing import List, Dict, Any, Type, Union # 确保可以找到本地模块 sys.path.append(str(Path(__file__).parent)) # 定义模块版本 __version__ = "1.2.0" class MissingModule: """缺失模块的占位实现""" def __init__(self, module_name: str): self.module_name = module_name print(f"警告:{module_name} 模块未实现") # 类型别名:模块类或缺失模块占位符 ModuleType = Union[Type[Any], MissingModule] def _import_class(module_name: str, class_name: str) -> ModuleType: """导入单个类""" try: module = __import__(f".{module_name}", fromlist=[class_name], level=1) return getattr(module, class_name) except (ImportError, AttributeError) as err: print(f"警告:{module_name}.{class_name} 导入失败 - {str(err)}") return MissingModule(f"{module_name}.{class_name}") # 导入模块类 InputAnalysisModule: ModuleType = _import_class('input_analysis', 'InputAnalysisModule') InputAnalyzer: ModuleType = _import_class('input_analysis', 'InputAnalyzer') CombinationAnalyzer: ModuleType = _import_class('combination_analysis', 'CombinationAnalyzer') CombinationAnalysisModule: ModuleType = _import_class('combination_analysis', 'CombinationAnalysisModule') FollowAnalyzer: ModuleType = _import_class('follow_analysis', 'FollowAnalyzer') FollowAnalysisModule: ModuleType = _import_class('follow_analysis', 'FollowAnalysisModule') TrendAnalyzer: ModuleType = _import_class('trend_analysis', 'TrendAnalyzer') TrendAnalysisModule: ModuleType = _import_class('trend_analysis', 'TrendAnalysisModule') NumberGenerator: ModuleType = _import_class('number_generation', 'NumberGenerator') DialogManager: ModuleType = _import_class('dialog_manager', 'DialogManager') # 设置NumberGenerationModule为NumberGenerator的别名 NumberGenerationModule = NumberGenerator def check_dependencies() -> bool: """检查依赖包版本""" try: import pandas as pd if not hasattr(pd, '__version__') or pd.__version__ < '1.3.0': raise RuntimeError("pandas版本需要>=1.3.0") return True except ImportError as err: raise RuntimeError(f"缺少必要依赖: {err}") from err def get_implemented_modules() -> List[str]: """返回已实现的模块列表""" implemented = [] for name, module in globals().items(): if name in [ 'InputAnalysisModule', 'InputAnalyzer', 'CombinationAnalyzer', 'CombinationAnalysisModule', 'FollowAnalyzer', 'FollowAnalysisModule', 'TrendAnalyzer', 'TrendAnalysisModule', 'NumberGenerator', 'NumberGenerationModule', 'DialogManager' ]: # 检查是否为类类型(非 MissingModule 实例) if isinstance(module, type): implemented.append(name) return implemented # 公共接口导出 __all__: List[str] = [ 'InputAnalysisModule', 'InputAnalyzer', 'CombinationAnalyzer', 'CombinationAnalysisModule', 'FollowAnalyzer', 'FollowAnalysisModule', 'TrendAnalyzer', 'TrendAnalysisModule', 'NumberGenerator', 'NumberGenerationModule', 'DialogManager', 'check_dependencies', 'get_implemented_modules' ]
08-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值