科研效率
未发现用户侧风险
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
元数据
| name | excel-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_sandbox | run_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