Try fix 'charmap' codec can't encode characters in position 16-23: character maps to <undefined>

This commit is contained in:
Xuwznln
2025-10-12 21:23:29 +08:00
parent ec882df36d
commit 05a3ff607a
3 changed files with 187 additions and 83 deletions

View File

@@ -41,8 +41,8 @@ jobs:
defaults: defaults:
run: run:
# Windows needs PowerShell for conda/mamba, Unix uses bash # Windows uses cmd for better conda/mamba compatibility, Unix uses bash
shell: ${{ matrix.platform == 'win-64' && 'pwsh' || 'bash -el {0}' }} shell: ${{ matrix.platform == 'win-64' && 'cmd /C CALL {0}' || 'bash -el {0}' }}
steps: steps:
- name: Check if platform should be built - name: Check if platform should be built
@@ -77,8 +77,16 @@ jobs:
auto-update-conda: false auto-update-conda: false
show-channel-urls: true show-channel-urls: true
- name: Install conda-pack, unilabos and dependencies - name: Install conda-pack, unilabos and dependencies (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo Installing unilabos and dependencies to unilab environment...
echo Using mamba for faster and more reliable dependency resolution...
mamba install uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
- name: Install conda-pack, unilabos and dependencies (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "Installing unilabos and dependencies to unilab environment..." echo "Installing unilabos and dependencies to unilab environment..."
echo "Using mamba for faster and more reliable dependency resolution..." echo "Using mamba for faster and more reliable dependency resolution..."
@@ -88,10 +96,11 @@ jobs:
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
id: msgs_version_win id: msgs_version_win
run: | run: |
Write-Host "Checking installed ros-humble-unilabos-msgs version..." echo Checking installed ros-humble-unilabos-msgs version...
$version = (conda list ros-humble-unilabos-msgs --json | ConvertFrom-Json)[0].version conda list ros-humble-unilabos-msgs
Write-Output "installed_version=$version" >> $env:GITHUB_OUTPUT for /f "tokens=2" %%i in ('conda list ros-humble-unilabos-msgs --json ^| python -c "import sys, json; pkgs=json.load(sys.stdin); print(pkgs[0]['version'] if pkgs else 'not-found')"') do set VERSION=%%i
Write-Host "Installed ros-humble-unilabos-msgs version: $version" echo installed_version=%VERSION% >> %GITHUB_OUTPUT%
echo Installed ros-humble-unilabos-msgs version: %VERSION%
- name: Get latest ros-humble-unilabos-msgs version (Unix) - name: Get latest ros-humble-unilabos-msgs version (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
@@ -103,29 +112,59 @@ jobs:
echo "installed_version=$VERSION" >> $GITHUB_OUTPUT echo "installed_version=$VERSION" >> $GITHUB_OUTPUT
echo "Installed ros-humble-unilabos-msgs version: $VERSION" echo "Installed ros-humble-unilabos-msgs version: $VERSION"
- name: Check for newer ros-humble-unilabos-msgs - name: Check for newer ros-humble-unilabos-msgs (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo Checking for available ros-humble-unilabos-msgs versions...
mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge --info || echo Search completed
echo Updating ros-humble-unilabos-msgs to latest version...
mamba update ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo Already at latest version
- name: Check for newer ros-humble-unilabos-msgs (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "Checking for available ros-humble-unilabos-msgs versions..." echo "Checking for available ros-humble-unilabos-msgs versions..."
mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge --info || echo "Search completed" mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge --info || echo "Search completed"
echo "Updating ros-humble-unilabos-msgs to latest version..." echo "Updating ros-humble-unilabos-msgs to latest version..."
mamba update ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo "Already at latest version" mamba update ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo "Already at latest version"
- name: Install latest unilabos from source - name: Install latest unilabos from source (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo Uninstalling existing unilabos...
pip uninstall unilabos -y || echo unilabos not installed via pip
echo Installing unilabos from source (branch: ${{ github.event.inputs.branch }})...
pip install .
echo Verifying installation...
pip show unilabos
- name: Install latest unilabos from source (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "Uninstalling existing unilabos..." echo "Uninstalling existing unilabos..."
pip uninstall unilabos -y || echo "unilabos not installed via pip" pip uninstall unilabos -y || echo "unilabos not installed via pip"
echo "Installing unilabos from source (branch: ${{ github.event.inputs.branch }})..." echo "Installing unilabos from source (branch: ${{ github.event.inputs.branch }})..."
pip install . pip install .
echo "Verifying installation..." echo "Verifying installation..."
pip show unilabos pip show unilabos
- name: Display environment info - name: Display environment info (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo === Environment Information ===
conda env list
echo.
echo === Installed Packages ===
conda list | findstr /C:"unilabos" /C:"ros-humble-unilabos-msgs" || conda list
echo.
echo === Python Packages ===
pip list | findstr unilabos || pip list
- name: Display environment info (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "=== Environment Information ===" echo "=== Environment Information ==="
conda env list conda env list
@@ -136,61 +175,79 @@ jobs:
echo "=== Python Packages ===" echo "=== Python Packages ==="
pip list | grep unilabos || pip list pip list | grep unilabos || pip list
- name: Verify environment integrity - name: Verify environment integrity (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo Verifying Python version...
python -c "import sys; print(f'Python version: {sys.version}')"
echo Verifying unilabos import...
python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo Warning: Could not import unilabos
echo Checking critical packages...
python -c "import rclpy; print('ROS2 rclpy: OK')"
echo Running comprehensive verification script...
python scripts\verify_installation.py || echo Warning: Verification script reported issues
echo Environment verification complete!
- name: Verify environment integrity (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "Verifying Python version..." echo "Verifying Python version..."
python -c "import sys; print(f'Python version: {sys.version}')" python -c "import sys; print(f'Python version: {sys.version}')"
echo "Verifying unilabos import..." echo "Verifying unilabos import..."
python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo "Warning: Could not import unilabos" python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo "Warning: Could not import unilabos"
echo "Checking critical packages..." echo "Checking critical packages..."
python -c "import rclpy; print('ROS2 rclpy: OK')" python -c "import rclpy; print('ROS2 rclpy: OK')"
echo "Running comprehensive verification script..." echo "Running comprehensive verification script..."
python scripts/verify_installation.py || echo "Warning: Verification script reported issues" python scripts/verify_installation.py || echo "Warning: Verification script reported issues"
echo "Environment verification complete!" echo "Environment verification complete!"
- name: Pack conda environment - name: Pack conda environment (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo Packing unilab environment with conda-pack...
conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files
echo Pack file created:
dir unilab-env-${{ matrix.platform }}.tar.gz
- name: Pack conda environment (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "Packing unilab environment with conda-pack..." echo "Packing unilab environment with conda-pack..."
conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files
echo "Pack file created:" echo "Pack file created:"
ls -lh unilab-env-${{ matrix.platform }}.tar.gz ls -lh unilab-env-${{ matrix.platform }}.tar.gz
- name: Prepare Windows distribution package - name: Prepare Windows distribution package
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: | run: |
Write-Host "==========================================" echo ==========================================
Write-Host "Creating distribution package..." echo Creating distribution package...
Write-Host "Platform: ${{ matrix.platform }}" echo Platform: ${{ matrix.platform }}
Write-Host "==========================================" echo ==========================================
New-Item -ItemType Directory -Force -Path dist-package | Out-Null mkdir dist-package 2>nul || cd .
# Copy packed environment rem Copy packed environment
Write-Host "Adding: unilab-env-${{ matrix.platform }}.tar.gz" echo Adding: unilab-env-${{ matrix.platform }}.tar.gz
Copy-Item unilab-env-${{ matrix.platform }}.tar.gz dist-package/ copy unilab-env-${{ matrix.platform }}.tar.gz dist-package\
# Copy installation script rem Copy installation script
Write-Host "Adding: install_unilab.bat" echo Adding: install_unilab.bat
Copy-Item scripts/install_unilab.bat dist-package/ copy scripts\install_unilab.bat dist-package\
# Copy verification script rem Copy verification script
Write-Host "Adding: verify_installation.py" echo Adding: verify_installation.py
Copy-Item scripts/verify_installation.py dist-package/ copy scripts\verify_installation.py dist-package\
# Create README using Python script rem Create README using Python script
Write-Host "Creating: README.txt" echo Creating: README.txt
python scripts/create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package/README.txt python scripts\create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package\README.txt
Write-Host "" echo.
Write-Host "Distribution package contents:" echo Distribution package contents:
Get-ChildItem dist-package | Format-Table Name, Length dir /b dist-package
Write-Host "" echo.
- name: Prepare Unix/Linux distribution package - name: Prepare Unix/Linux distribution package
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
@@ -227,26 +284,26 @@ jobs:
- name: Create Windows ZIP archive - name: Create Windows ZIP archive
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: | run: |
Write-Host "==========================================" echo ==========================================
Write-Host "Creating Windows ZIP archive (ZIP64 support for large files)..." echo Creating Windows ZIP archive (ZIP64 support for large files)...
Write-Host "Archive: unilab-pack-${{ matrix.platform }}.zip" echo Archive: unilab-pack-${{ matrix.platform }}.zip
Write-Host "Contents: install_unilab.bat + unilab-env-${{ matrix.platform }}.tar.gz + extras" echo Contents: install_unilab.bat + unilab-env-${{ matrix.platform }}.tar.gz + extras
Write-Host "" echo.
# Use Python script with ZIP64 support instead of PowerShell Compress-Archive rem Use Python script with ZIP64 support instead of PowerShell Compress-Archive
# PowerShell Compress-Archive has a 2GB limitation rem PowerShell Compress-Archive has a 2GB limitation
python scripts/create_zip_archive.py dist-package unilab-pack-${{ matrix.platform }}.zip python scripts\create_zip_archive.py dist-package unilab-pack-${{ matrix.platform }}.zip
Write-Host "==========================================" echo ==========================================
Write-Host "" echo.
Write-Host "Final package created:" echo Final package created:
Get-ChildItem unilab-pack-* | Format-Table Name, Length dir unilab-pack-*
Write-Host "" echo.
Write-Host "Users can now:" echo Users can now:
Write-Host " 1. Download unilab-pack-${{ matrix.platform }}.zip" echo 1. Download unilab-pack-${{ matrix.platform }}.zip
Write-Host " 2. Extract it" echo 2. Extract it
Write-Host " 3. Run install_unilab.bat" echo 3. Run install_unilab.bat
Write-Host "" echo.
- name: Create Unix/Linux TAR.GZ archive - name: Create Unix/Linux TAR.GZ archive
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
@@ -278,8 +335,32 @@ jobs:
retention-days: 90 retention-days: 90
if-no-files-found: error if-no-files-found: error
- name: Display package info - name: Display package info (Windows)
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: |
echo ==========================================
echo Build Summary
echo ==========================================
echo Platform: ${{ matrix.platform }}
echo Branch: ${{ github.event.inputs.branch }}
echo Python version: 3.11.11
echo.
echo Package contents:
echo - unilab-pack-${{ matrix.platform }}.zip
echo - unilab-env-${{ matrix.platform }}.tar.gz (packed environment)
echo - install_unilab.bat
echo - verify_installation.py
echo - README.txt
echo.
echo Package size:
dir unilab-pack-*
echo.
echo Download the artifact and run the install script!
echo ==========================================
- name: Display package info (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash
run: | run: |
echo "==========================================" echo "=========================================="
echo "Build Summary" echo "Build Summary"
@@ -289,18 +370,14 @@ jobs:
echo "Python version: 3.11.11" echo "Python version: 3.11.11"
echo "" echo ""
echo "Package contents:" echo "Package contents:"
if [ "${{ matrix.platform }}" == "win-64" ]; then echo " - unilab-pack-${{ matrix.platform }}.tar.gz"
echo " - unilab-pack-${{ matrix.platform }}.zip"
else
echo " - unilab-pack-${{ matrix.platform }}.tar.gz"
fi
echo " - unilab-env-${{ matrix.platform }}.tar.gz (packed environment)" echo " - unilab-env-${{ matrix.platform }}.tar.gz (packed environment)"
echo " - install_unilab script" echo " - install_unilab.sh"
echo " - verify_installation.py" echo " - verify_installation.py"
echo " - README.txt" echo " - README.txt"
echo "" echo ""
echo "Package size:" echo "Package size:"
ls -lh unilab-pack-* 2>/dev/null || ls -lh unilab-env-${{ matrix.platform }}.tar.gz ls -lh unilab-pack-*
echo "" echo ""
echo "Download the artifact and run the install script!" echo "Download the artifact and run the install script!"
echo "==========================================" echo "=========================================="

View File

@@ -16,6 +16,32 @@ Usage:
""" """
import sys import sys
import os
# IMPORTANT: Set UTF-8 encoding BEFORE any other imports
# This ensures all subsequent imports (including unilabos) can output UTF-8 characters
if sys.platform == "win32":
# Method 1: Reconfigure stdout/stderr to use UTF-8 with error handling
try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
except (AttributeError, OSError):
pass
# Method 2: Set environment variable for subprocess and console
os.environ["PYTHONIOENCODING"] = "utf-8"
# Method 3: Try to change Windows console code page to UTF-8
try:
import ctypes
# Set console code page to UTF-8 (CP 65001)
ctypes.windll.kernel32.SetConsoleCP(65001)
ctypes.windll.kernel32.SetConsoleOutputCP(65001)
except (ImportError, AttributeError, OSError):
pass
# Now import other modules
import importlib import importlib
# Use ASCII-safe symbols that work across all platforms # Use ASCII-safe symbols that work across all platforms
@@ -55,7 +81,7 @@ def check_python_version() -> bool:
print(f" {CHECK_MARK} Python {version_str}") print(f" {CHECK_MARK} Python {version_str}")
return True return True
else: else:
print(f" {CROSS_MARK} Python {version_str} (requires Python 3.8+)") print(f" {CROSS_MARK} Python {version_str} (requires Python 3.11+)")
return False return False
@@ -122,7 +148,7 @@ def main():
print("\nTroubleshooting:") print("\nTroubleshooting:")
print(" 1. Ensure you're in the correct conda environment: conda activate unilab") print(" 1. Ensure you're in the correct conda environment: conda activate unilab")
print(" 2. Check the installation documentation: docs/user_guide/installation.md") print(" 2. Check the installation documentation: docs/user_guide/installation.md")
print(" 3. Try reinstalling: pip install -e .") print(" 3. Try reinstalling: pip install .")
return 1 return 1

View File

@@ -7,6 +7,7 @@ import argparse
import importlib import importlib
import subprocess import subprocess
import sys import sys
from .banner_print import print_status from .banner_print import print_status
@@ -49,17 +50,17 @@ class EnvironmentChecker:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=300) # 5分钟超时 result = subprocess.run(cmd, capture_output=True, text=True, timeout=300) # 5分钟超时
if result.returncode == 0: if result.returncode == 0:
print_status(f" {package_name} 安装成功", "success") print_status(f" {package_name} 安装成功", "success")
return True return True
else: else:
print_status(f" {package_name} 安装失败: {result.stderr}", "error") print_status(f"× {package_name} 安装失败: {result.stderr}", "error")
return False return False
except subprocess.TimeoutExpired: except subprocess.TimeoutExpired:
print_status(f" {package_name} 安装超时", "error") print_status(f"× {package_name} 安装超时", "error")
return False return False
except Exception as e: except Exception as e:
print_status(f" {package_name} 安装异常: {str(e)}", "error") print_status(f"× {package_name} 安装异常: {str(e)}", "error")
return False return False
def check_all_packages(self) -> bool: def check_all_packages(self) -> bool:
@@ -77,7 +78,7 @@ class EnvironmentChecker:
self.missing_packages.append((package_name, install_url)) self.missing_packages.append((package_name, install_url))
if not self.missing_packages: if not self.missing_packages:
print_status(" 所有依赖包检查完成,环境正常", "success") print_status(" 所有依赖包检查完成,环境正常", "success")
return True return True
print_status(f"发现 {len(self.missing_packages)} 个缺失的包", "warning") print_status(f"发现 {len(self.missing_packages)} 个缺失的包", "warning")
@@ -109,7 +110,7 @@ class EnvironmentChecker:
print_status(f" - {import_name} (pip install {pip_name})", "error") print_status(f" - {import_name} (pip install {pip_name})", "error")
return False return False
print_status(f" 成功安装 {success_count} 个包", "success") print_status(f" 成功安装 {success_count} 个包", "success")
return True return True
def verify_installation(self) -> bool: def verify_installation(self) -> bool:
@@ -130,7 +131,7 @@ class EnvironmentChecker:
print_status(f" - {import_name}", "error") print_status(f" - {import_name}", "error")
return False return False
print_status(" 所有包验证通过", "success") print_status(" 所有包验证通过", "success")
return True return True