科研技能库/Excel Shell Heredoc 回退方案
科研效率
未发现用户侧风险

Excel Shell Heredoc 回退方案

当沙箱执行失败时,通过基于 shell 的 Python heredoc 回退来使用 openpyxl 创建 Excel 文件。

文件预览

2 个文件
SKILL.md
6.5 KB · 可预览
---
name: excel-heredoc-fallback
description: Create Excel files with openpyxl by falling back to shell-based Python heredoc when sandbox execution fails
---

# Excel Creation via Shell Heredoc Fallback

## Overview

When creating Excel files with openpyxl, `execute_code_sandbox` may fail due to sandbox restrictions, missing dependencies, or permission issues. This skill provides a reliable fallback: execute Python code via `run_shell` using an inline heredoc script. This approach often succeeds where the sandbox fails and supports full openpyxl features including styling, formulas, and formatting.

## When to Use This Skill

- `execute_code_sandbox` fails when importing or using openpyxl
- Sandbox shows errors about missing packages, permissions, or execution restrictions
- You need to create Excel files with advanced formatting (styles, colors, merged cells, formulas)
- Previous sandbox attempts have failed multiple times

## Step-by-Step Instructions

### Step 1: Attempt Sandbox Execution First

Always try `execute_code_sandbox` first, as it's cleaner and preferred when it works:

```python
from openpyxl import Workbook
from openpyxl.styles import Font, Fill, PatternFill, Alignment

wb = Workbook()
ws = wb.active
ws['A1'] = 'Header'
ws['A1'].font = Font(bold=True)
wb.save('output.xlsx')
```

### Step 2: Detect Sandbox Failure

Watch for these failure indicators:
- ImportError for openpyxl or related modules
- Permission denied errors
- File write failures
- Repeated retry loops without success
- Timeout or resource errors

### Step 3: Fall Back to Shell Heredoc

When sandbox fails, switch to `run_shell` with a Python heredoc:

```bash
python3 << 'EOF'
from openpyxl import Workbook
from openpyxl.styles import Font, Fill, PatternFill, Alignment, Border, Side

# Create workbook
wb = Workbook()
ws = wb.active
ws.title = "Sheet1"

# Add data with formatting
ws['A1'] = 'Name'
ws['B1'] = 'Value'
ws['A1'].font = Font(bold=True, size=14)
ws['B1'].font = Font(bold=True, size=14)

# Add rows
data = [
    ['Item 1', 100],
    ['Item 2', 200],
    ['Item 3', 150],
]

for row_idx, row_data in enumerate(data, start=2):
    for col_idx, value in enumerate(row_data, start=1):
        cell = ws.cell(row=row_idx, column=col_idx, value=value)
        cell.alignment = Alignment(horizontal='center')

# Add formulas if needed
ws['B5'] = '=SUM(B2:B4)'

# Save the file
wb.save('output.xlsx')
print("Excel file created successfully: output.xlsx")
EOF
```

### Step 4: Use run_shell Tool

Execute the heredoc via `run_shell`:

```
tool: run_shell
command: python3 << 'EOF'
[from openpyxl code here]
EOF
```

### Step 5: Verify File Creation

After execution, confirm the file was created:

```
tool: run_shell
command: ls -lh output.xlsx
```

Check the file size to ensure it's not empty (should be >1KB for typical spreadsheets).

## Best Practices

### 1. Use Single-Quoted Heredoc Delimiter

Always use `<< 'EOF'` (with quotes) to prevent shell variable expansion inside the Python code.

### 2. Include Error Handling

Add try/except blocks to catch and report issues:

```python
try:
    from openpyxl import Workbook
    # ... your code ...
    wb.save('output.xlsx')
    print("SUCCESS: File created")
except Exception as e:
    print(f"ERROR: {e}")
    exit(1)
```

### 3. Print Confirmation Messages

Always include print statements that confirm success or report specific errors. This helps debug issues.

### 4. Use Absolute or Explicit Paths

When saving files, use explicit paths to avoid confusion:

```python
wb.save('./output.xlsx')  # Explicit current directory
# or
wb.save('/workspace/output.xlsx')  # Absolute path
```

### 5. Keep Scripts Concise

Heredoc scripts should be focused and not excessively long. If the Excel logic is complex, consider writing a separate `.py` file first using `write_file`, then executing it.

## Advanced Formatting Examples

### Cell Styling

```python
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

# Define styles
bold_font = Font(bold=True, size=12)
header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
center_align = Alignment(horizontal='center', vertical='center')
thin_border = Border(
    left=Side(style='thin'),
    right=Side(style='thin'),
    top=Side(style='thin'),
    bottom=Side(style='thin')
)

# Apply to cells
ws['A1'].font = bold_font
ws['A1'].fill = header_fill
ws['A1'].alignment = center_align
```

### Column Width and Row Height

```python
ws.column_dimensions['A'].width = 20
ws.column_dimensions['B'].width = 15
ws.row_dimensions[1].height = 25
```

### Merged Cells

```python
ws.merge_cells('A1:C1')
ws['A1'] = 'Merged Header'
ws['A1'].alignment = Alignment(horizontal='center')
```

### Multiple Sheets

```python
wb.create_sheet(title='Summary')
wb.create_sheet(title='Details')
ws_summary = wb['Summary']
ws_details = wb['Details']
```

## Troubleshooting

| Issue | Solution |
|-------|----------|
| openpyxl not found | Add `pip install openpyxl` before Python script |
| File not created | Check working directory, use absolute paths |
| Permission denied | Ensure write permissions in target directory |
| Encoding issues | Python 3 handles UTF-8 by default; specify if needed |
| Large files time out | Increase `run_shell` timeout parameter |

## Comparison: Sandbox vs. Shell Heredoc

| Aspect | execute_code_sandbox | run_shell heredoc |
|--------|---------------------|-------------------|
| Preferred | Yes (cleaner) | No (fallback) |
| Dependencies | May be restricted | Uses system Python |
| File access | Sandboxed | Full filesystem |
| Styling support | Sometimes limited | Full support |
| Debugging | Logs in tool output | Full stdout/stderr |

## Example Complete Workflow

```
# Step 1: Try sandbox
tool: execute_code_sandbox
code: |
  from openpyxl import Workbook
  wb = Workbook()
  ws = wb.active
  ws['A1'] = 'Test'
  wb.save('test.xlsx')

# Step 2: If that fails, use shell heredoc
tool: run_shell
command: |
  python3 << 'EOF'
  from openpyxl import Workbook
  from openpyxl.styles import Font, PatternFill
  
  wb = Workbook()
  ws = wb.active
  
  ws['A1'] = 'Header'
  ws['A1'].font = Font(bold=True)
  ws['A1'].fill = PatternFill(start_color='FFFF00', fill_type='solid')
  
  wb.save('test.xlsx')
  print("Created: test.xlsx")
  EOF

# Step 3: Verify
tool: run_shell
command: ls -lh test.xlsx
```

SKILL.md

元数据
nameexcel-heredoc-fallback
description当沙箱执行失败时,通过基于 shell 的 Python heredoc 回退来使用 openpyxl 创建 Excel 文件

通过 Shell Heredoc 回退创建 Excel

概述

当使用 openpyxl 创建 Excel 文件时,execute_code_sandbox 可能由于沙箱限制、缺少依赖或权限问题而失败。本技能提供了一种可靠的备选方案:通过 run_shell 使用内联 heredoc 脚本执行 Python 代码。这种方法在沙箱失败时往往能成功,并支持完整的 openpyxl 功能,包括样式、公式和格式设置。

适用场景

  • execute_code_sandbox 在导入或使用 openpyxl 时失败
  • 沙箱显示关于缺失包、权限或执行限制的错误
  • 需要创建具有高级格式的 Excel 文件(样式、颜色、合并单元格、公式)
  • 先前的沙箱尝试多次失败

分步说明

第 1 步:首先尝试沙箱执行

始终先尝试 execute_code_sandbox,它更简洁且在工作时是首选:

python
from openpyxl import Workbook
from openpyxl.styles import Font, Fill, PatternFill, Alignment

wb = Workbook()
ws = wb.active
ws['A1'] = 'Header'
ws['A1'].font = Font(bold=True)
wb.save('output.xlsx')

第 2 步:检测沙箱故障

留意以下故障迹象:

  • 导入 openpyxl 或相关模块时出现 ImportError
  • 权限被拒绝错误
  • 文件写入失败
  • 重复的重试循环未成功
  • 超时或资源错误

第 3 步:回退到 Shell Heredoc

当沙箱失败时,切换到 run_shell 并配合 Python heredoc:

bash
python3 << 'EOF'
from openpyxl import Workbook
from openpyxl.styles import Font, Fill, PatternFill, Alignment, Border, Side

# 创建工作簿
wb = Workbook()
ws = wb.active
ws.title = "Sheet1"

# 添加带格式的数据
ws['A1'] = 'Name'
ws['B1'] = 'Value'
ws['A1'].font = Font(bold=True, size=14)
ws['B1'].font = Font(bold=True, size=14)

# 添加行
data = [
    ['Item 1', 100],
    ['Item 2', 200],
    ['Item 3', 150],
]

for row_idx, row_data in enumerate(data, start=2):
    for col_idx, value in enumerate(row_data, start=1):
        cell = ws.cell(row=row_idx, column=col_idx, value=value)
        cell.alignment = Alignment(horizontal='center')

# 如果需要,添加公式
ws['B5'] = '=SUM(B2:B4)'

# 保存文件
wb.save('output.xlsx')
print("Excel 文件已成功创建: output.xlsx")
EOF

第 4 步:使用 run_shell 工具

通过 run_shell 执行 heredoc:

text
tool: run_shell
command: python3 << 'EOF'
[此处是 openpyxl 代码]
EOF

第 5 步:验证文件创建

执行后,确认文件已创建:

text
tool: run_shell
command: ls -lh output.xlsx

检查文件大小确保它不为空(典型电子表格应 >1KB)。

最佳实践

1. 使用单引号 heredoc 定界符

始终使用 << 'EOF'(带引号),以防止 shell 在 Python 代码中进行变量扩展。

2. 包含错误处理

添加 try/except 块来捕获和报告问题:

python
try:
    from openpyxl import Workbook
    # ... 你的代码 ...
    wb.save('output.xlsx')
    print("成功: 文件已创建")
except Exception as e:
    print(f"错误: {e}")
    exit(1)

3. 打印确认消息

始终包含 print 语句来确认成功或报告具体错误。这有助于调试。

4. 使用绝对路径或显式路径

保存文件时,使用显式路径以避免混淆:

python
wb.save('./output.xlsx')  # 显式当前目录
# 或
wb.save('/workspace/output.xlsx')  # 绝对路径

5. 保持脚本简洁

Heredoc 脚本应专注且不宜过长。如果 Excel 逻辑复杂,可考虑先用 write_file 编写单独的 .py 文件,然后再执行它。

高级格式示例

单元格样式

python
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

# 定义样式
bold_font = Font(bold=True, size=12)
header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
center_align = Alignment(horizontal='center', vertical='center')
thin_border = Border(
    left=Side(style='thin'),
    right=Side(style='thin'),
    top=Side(style='thin'),
    bottom=Side(style='thin')
)

# 应用到单元格
ws['A1'].font = bold_font
ws['A1'].fill = header_fill
ws['A1'].alignment = center_align

列宽和行高

python
ws.column_dimensions['A'].width = 20
ws.column_dimensions['B'].width = 15
ws.row_dimensions[1].height = 25

合并单元格

python
ws.merge_cells('A1:C1')
ws['A1'] = 'Merged Header'
ws['A1'].alignment = Alignment(horizontal='center')

多工作表

python
wb.create_sheet(title='Summary')
wb.create_sheet(title='Details')
ws_summary = wb['Summary']
ws_details = wb['Details']

故障排除

问题解决方案
找不到 openpyxl在 Python 脚本之前添加 pip install openpyxl
文件未创建检查工作目录,使用绝对路径
权限被拒绝确保目标目录有写入权限
编码问题Python 3 默认处理 UTF-8;如有需要可指定
大文件超时增加 run_shell 的超时参数

对比:沙箱 vs. Shell Heredoc

方面execute_code_sandboxrun_shell heredoc
首选是(更简洁)否(回退方案)
依赖可能受限使用系统 Python
文件访问受沙箱限制完全文件系统
样式支持有时有限完全支持
调试工具输出中的日志完整的 stdout/stderr

完整工作流示例

text
# 第 1 步:尝试沙箱
tool: execute_code_sandbox
code: |
  from openpyxl import Workbook
  wb = Workbook()
  ws = wb.active
  ws['A1'] = 'Test'
  wb.save('test.xlsx')

# 第 2 步:如果失败,使用 shell heredoc
tool: run_shell
command: |
  python3 << 'EOF'
  from openpyxl import Workbook
  from openpyxl.styles import Font, PatternFill
  
  wb = Workbook()
  ws = wb.active
  
  ws['A1'] = 'Header'
  ws['A1'].font = Font(bold=True)
  ws['A1'].fill = PatternFill(start_color='FFFF00', fill_type='solid')
  
  wb.save('test.xlsx')
  print("已创建: test.xlsx")
  EOF

# 第 3 步:验证
tool: run_shell
command: ls -lh test.xlsx