ย้ายไปยังเอนจิ้น Python-to-.NET ใหม่ในเวอร์ชัน 26.8
บทนำ
เวอร์ชัน 26.8 แทนที่เอ็นจิินที่เชื่อมต่อ Python กับ .NET. primitive การวาดถูกย้ายไปยังโมดูล aspose.slides.
ข้ามไปที่ ฉันมีข้อผิดพลาด หากคุณมีปัญหา หลังการอัพเกรด.
Primitive การวาดที่ย้ายไปยัง aspose.slides
มีการย้ายชนิดทั้งหมดเจ็ดชนิด. ชนิดเหล่านี้เก็บชื่อ, อาร์กิวเมนต์, และพฤติกรรมไว้เหมือนเดิม:
| ประเภท | ก่อน 26.8 | 26.8 และหลัง |
|---|---|---|
| Point | aspose.pydrawing.Point |
aspose.slides.Point |
| PointF | aspose.pydrawing.PointF |
aspose.slides.PointF |
| Size | aspose.pydrawing.Size |
aspose.slides.Size |
| SizeF | aspose.pydrawing.SizeF |
aspose.slides.SizeF |
| Rectangle | aspose.pydrawing.Rectangle |
aspose.slides.Rectangle |
| RectangleF | aspose.pydrawing.RectangleF |
aspose.slides.RectangleF |
| Color | aspose.pydrawing.Color |
aspose.slides.Color |
เจ็ดชนิดนี้เป็นเนื้อหาที่เหลือทั้งหมดของ aspose.pydrawing. หลังจากที่คุณได้ชี้ใหม่แล้ว, โค้ดของคุณไม่จำเป็นต้องอ้างอิง aspose.pydrawing อีกเลย, และการนำเข้าทั้งหมดของมันสามารถลบได้. สิ่งนี้ทำให้การตรวจสอบผลลัพธ์ง่ายขึ้น - ดู ตรวจสอบการย้าย.
โค้ดเก่า:
import aspose.slides as slides
import aspose.pydrawing as drawing
with slides.Presentation() as presentation:
slide = presentation.slides[0]
shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 50, 50, 200, 100)
shape.fill_format.fill_type = slides.FillType.SOLID
shape.fill_format.solid_fill_color.color = drawing.Color.red
with slide.get_image(drawing.Size(1920, 1080)) as slide_image:
slide_image.save("slide1.jpeg", slides.ImageFormat.JPEG)
เวอร์ชัน 26.8:
import aspose.slides as slides
with slides.Presentation() as presentation:
slide = presentation.slides[0]
shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 50, 50, 200, 100)
shape.fill_format.fill_type = slides.FillType.SOLID
shape.fill_format.solid_fill_color.color = slides.Color.red
with slide.get_image(slides.Size(1920, 1080)) as slide_image:
slide_image.save("slide1.jpeg", slides.ImageFormat.JPEG)
รูปแบบการนำเข้า from มีการเปลี่ยนแปลงในลักษณะเดียวกัน:
# โค้ดเก่า
from aspose.pydrawing import Color, Point
# เวอร์ชัน 26.8
from aspose.slides import Color, Point
แก้ไขข้อผิดพลาดการนำเข้า
ค้นหา traceback ของคุณในคอลัมน์แรก.
| ข้อผิดพลาด | สาเหตุ | การแก้ไข |
|---|---|---|
AttributeError: module 'aspose.pydrawing' has no attribute 'Color' (or Point, Rectangle, and so on) |
แพคเกจเป็น 26.8, โค้ดยังชี้ไปที่โมดูลเก่า | อัปเดตโค้ดของคุณ |
ImportError: cannot import name 'Color' from 'aspose.pydrawing' |
สาเหตุเดียวกัน, รูปแบบการนำเข้า from |
อัปเดตโค้ดของคุณ |
ModuleNotFoundError: No module named 'aspose.pydrawing' |
โมดูลและชนิดทั้งเจ็ดได้ย้ายไปยัง aspose.slides |
อัปเดตโค้ดของคุณ, แล้วลบการนำเข้า aspose.pydrawing |
ImportError: cannot import name 'Color' from 'aspose.slides' |
โค้ดได้ทำการย้ายแล้ว, แต่แพคเกจที่ติดตั้งคือ 26.7 หรือเก่ากว่า | pip install --upgrade aspose.slides |
TypeError on a color, point, or size argument |
ค่าที่สร้างจาก aspose.pydrawing ถูกส่งไปยัง API ใหม่ |
สร้างค่าโดยใช้ aspose.slides ด้วยเช่นกัน |
อัปเดตโค้ดของคุณ
เนื่องจาก aspose.pydrawing ไม่มีเนื้อหาอื่นนอกจากชนิดเจ็ดที่ย้าย, การย้ายคือการเปลี่ยนชื่อของโมดูล. รูปแบบการนำเข้าทั้งหมดจะครอบคลุมด้วยการเปลี่ยนชื่อนี้, รวมถึง alias:
# โค้ดเก่า
import aspose.pydrawing as drawing
color = drawing.Color.red
# เวอร์ชัน 26.8 - alias ยังคงทำงาน
import aspose.slides as drawing
color = drawing.Color.red
สิ่งนี้ใช้ได้ในทุกสโคป, รวมถึงภายในบอดี้ของฟังก์ชัน, เพราะ alias ยังคงผูกไว้ในตำแหน่งเดิม. ข้อจำกัดเดียวคือชื่อที่อาจทำให้เข้าใจผิด, ดังนั้นพิจารณาให้เจตนาเป็นลักษณะชัดเจน:
import aspose.slides as slides
color = slides.Color.red
เลือกวิธีที่ตรงกับขนาดของฐานโค้ดของคุณ.
แทนที่ด้วยตนเอง
สำหรับไฟล์ไม่กี่ไฟล์, ค้นหา aspose.pydrawing และแทนที่ด้วย aspose.slides, แล้วลบการนำเข้าที่ไม่จำเป็นอีกต่อไป.
แทนที่ด้วยคำสั่ง Shell
นี่เป็นการแทนที่แบบข้อความธรรมดา, ดังนั้นจึงส่งผลต่อการปรากฏในสตริงและคอมเมนต์ด้วย. ทั้งสองคำสั่งจะเขียนไฟล์สำเนา .bak ของทุกไฟล์ที่เปลี่ยนแปลง.
Linux:
grep -rlZ --include='*.py' 'aspose\.pydrawing' . \
| xargs -0 -r sed -i.bak 's/aspose\.pydrawing/aspose.slides/g'
บน macOS, ใช้ sed -i '' แทน sed -i.bak, หรือทำการติดตั้ง GNU sed เป็น gsed.
Windows PowerShell:
Get-ChildItem -Recurse -Filter *.py | ForEach-Object {
$t = Get-Content $_ -Raw
$new = $t -replace 'aspose\.pydrawing', 'aspose.slides'
if ($new -ne $t) {
Copy-Item $_.FullName "$($_.FullName).bak"
Set-Content $_.FullName $new -NoNewline
$_.FullName
}
}
เพื่อกู้คืนบน Linux หรือ macOS:
find . -name '*.py.bak' -exec sh -c 'mv "$1" "${1%.bak}"' _ {} \;
เพื่อกู้คืนบน Windows:
Get-ChildItem -Recurse -Filter *.py.bak | ForEach-Object {
Move-Item $_.FullName ($_.FullName -replace '\.bak$', '') -Force
}
แทนที่ด้วยสคริปต์ Python
การเปลี่ยนชื่อเดียวกัน, พกพาได้บน Linux, macOS, และ Windows. สคริปต์รับพาธเป็นอาร์กิวเมนต์และแสดงตัวอย่างการเปลี่ยนแปลงหากไม่ได้ส่ง --write. เพิ่ม --backup เพื่อเก็บสำเนา .bak ของทุกไฟล์ที่เปลี่ยน. บันทึกเป็นชื่อใดก็ได้ - ข้อความการใช้งานจะดึงชื่อขึ้นมาขณะรัน.
"""เปลี่ยนชื่อ aspose.pydrawing เป็น aspose.slides การแทนที่เป็นข้อความธรรมดา.
python <this script> src/ # แสดงตัวอย่าง
python <this script> src/ --write # ใช้งาน
python <this script> src/ --write --backup # ใช้งาน, เก็บสำเนา .bak
"""
import sys
from pathlib import Path
W = "--write" in sys.argv
B = "--backup" in sys.argv
ROOT = next((a for a in sys.argv[1:] if not a.startswith("-")), None)
if ROOT is None:
sys.exit(f"usage: python {Path(sys.argv[0]).name} <path> [--write] [--backup]")
root = Path(ROOT)
if not root.exists():
sys.exit(f"no such path: {root}")
files = [root] if root.is_file() else root.rglob("*.py")
changed = 0
for p in files:
if {".venv", "venv", "__pycache__", ".git"} & set(p.parts):
continue
s = p.read_text(encoding="utf-8")
n = s.replace("aspose.pydrawing", "aspose.slides")
if n == s:
continue
changed += 1
print(("wrote " if W else "would change ") + str(p))
if W:
if B:
p.with_suffix(p.suffix + ".bak").write_text(s, encoding="utf-8")
p.write_text(n, encoding="utf-8")
print(f"{changed} file(s) {'changed' if W else 'to change'}"
+ ("" if W or not changed else "; rerun with --write to apply"))
การเรียกใช้งานทั่วไปมีลักษณะดังนี้:
$ python migrate.py src/
would change src/render.py
would change src/export/slides.py
2 file(s) to change; rerun with --write to apply
$ python migrate.py src/ --write --backup
wrote src/render.py
wrote src/export/slides.py
2 file(s) changed
พาธสามารถเป็นไดเรกทอรีที่สแกนแบบรีเคอร์ซีฟ, หรือไฟล์ .py เพียงไฟล์เดียว.
แทนที่ด้วยสคริปต์ที่ใช้ AST
แนะนำสำหรับฐานโค้ดที่ใหญ่กว่า. สคริปต์นี้ทำการเปลี่ยนชื่อเดียวกัน, แต่จะพาร์เซไฟล์แต่ละไฟล์ก่อน, ดังนั้นจะไม่แตะต้องการปรากฏในสตริง, คอมเมนต์, หรือ docstring.
เพราะสคริปต์เปลี่ยนชื่อโมดูลในที่และปล่อย alias ไว้, รูปแบบการนำเข้าทุกแบบจะถูกจัดการโดยไม่มีกรณีพิเศษ: import aspose.pydrawing, import aspose.pydrawing as X, from aspose.pydrawing import Color, from aspose.pydrawing import Color as C, การนำเข้าแบบหลายบรรทัดในวงเล็บ, การนำเข้าในฟังก์ชัน, และการส่งโมดูลเป็นค่า. รองรับ флаг --write และ --backup เหมือนเดิม.
"""Rename aspose.pydrawing to aspose.slides, skipping strings and comments.
python <this script> src/ # preview
python <this script> src/ --write # apply
python <this script> src/ --write --backup # apply, keeping .bak copies
"""
import ast, sys
from pathlib import Path
MOD, DST = "aspose.pydrawing", "aspose.slides"
W = "--write" in sys.argv
B = "--backup" in sys.argv
ROOT = next((a for a in sys.argv[1:] if not a.startswith("-")), None)
if ROOT is None:
sys.exit(f"usage: python {Path(sys.argv[0]).name} <path> [--write] [--backup]")
root = Path(ROOT)
if not root.exists():
sys.exit(f"no such path: {root}")
files = [root] if root.is_file() else root.rglob("*.py")
changed = 0
def chain(n):
p = []
while isinstance(n, ast.Attribute):
p.append(n.attr)
n = n.value
return ".".join(reversed(p + [n.id])) if isinstance(n, ast.Name) else None
def fix(src):
tree = ast.parse(src)
off, o = [], 0
for l in src.encode().splitlines(keepends=True):
off.append(o)
o += len(l)
off.append(o)
edits = []
for n in ast.walk(tree):
# นำเข้า aspose.pydrawing [as X] / from aspose.pydrawing import ...
# ชื่อโมดูลถูกเปลี่ยนชื่อในที่, ดังนั้น alias ใดก็ยังคงผูกอยู่เหมือนเดิม
if (isinstance(n, ast.Import) and any(a.name == MOD for a in n.names)) or \
(isinstance(n, ast.ImportFrom) and n.module == MOD):
s, e = off[n.lineno - 1], off[n.end_lineno - 1] + n.end_col_offset
edits.append((s, e, src.encode()[s:e].decode().replace(MOD, DST)))
# นิพจน์ใดๆ ที่อ้างอิงโมดูล, รวมถึง `fn(aspose.pydrawing)` อย่างเดียว
elif isinstance(n, ast.Attribute) and chain(n) == MOD:
edits.append((off[n.lineno - 1] + n.col_offset,
off[n.end_lineno - 1] + n.end_col_offset, DST))
b = src.encode()
for s, e, r in sorted(edits, reverse=True): # การทำจากหลังไปหน้า ทำให้ตำแหน่งออฟเซ็ตยังคงถูกต้อง
b = b[:s] + r.encode() + b[e:]
return b.decode()
for p in files:
if {".venv", "venv", "__pycache__", ".git"} & set(p.parts):
continue
s = p.read_text(encoding="utf-8")
try:
n = fix(s)
except SyntaxError as e:
print(f"skipped {p}: {e}")
continue
if n != s:
print(("wrote " if W else "would change ") + str(p))
if W:
if B:
p.with_suffix(p.suffix + ".bak").write_text(s, encoding="utf-8")
p.write_text(n, encoding="utf-8")
สคริปต์ทั้งสองเป็น idempotent: การรันซ้ำบนโค้ดที่ย้ายแล้วจะไม่เปลี่ยนแปลงอะไรเลย.
ตรวจสอบการย้าย
การค้นหาข้อความจะแสดงว่ามีอะไรเหลืออยู่หรือไม่:
grep -rn 'aspose\.pydrawing' --include='*.py' --exclude-dir=.venv .
การตรวจสอบนี้รวดเร็ว, แต่ก็จะจับคู่ในสตริงและคอมเมนต์ด้วย, ดังนั้นโค้ดที่สะอาดอาจยังพบผลลัพธ์. เพื่อคำตอบที่ชัดเจน, ใช้การตรวจสอบด้านล่าง. มันรายงานเฉพาะการอ้างอิงโค้ดจริงและออกด้วยสถานะไม่เป็นศูนย์หากเหลืออะไร, ทำให้ใช้เป็นเกตการสร้างได้.
import ast, sys
from pathlib import Path
MOD = "aspose.pydrawing"
ROOT = next((a for a in sys.argv[1:] if not a.startswith("-")), ".")
def chain(n):
p = []
while isinstance(n, ast.Attribute):
p.append(n.attr)
n = n.value
return ".".join(reversed(p + [n.id])) if isinstance(n, ast.Name) else None
def scan(tree):
for n in ast.walk(tree):
if isinstance(n, ast.Import) and any(a.name == MOD for a in n.names):
yield n.lineno, f"import {MOD}"
elif isinstance(n, ast.ImportFrom) and n.module == MOD:
names = ", ".join(a.name for a in n.names)
yield n.lineno, f"from {MOD} import {names}"
elif isinstance(n, ast.Attribute) and chain(n) == MOD:
yield n.lineno, f"reference to {MOD}"
hits = 0
for p in sorted(Path(ROOT).rglob("*.py")):
if {".venv", "venv", "__pycache__", ".git"} & set(p.parts):
continue
try:
tree = ast.parse(p.read_text(encoding="utf-8"))
except SyntaxError as e:
print(f"skipped {p}: {e}")
continue
for lineno, what in sorted(scan(tree)):
print(f"{p}:{lineno}: {what}")
hits += 1
print("migration complete" if not hits else f"{hits} reference(s) left")
sys.exit(1 if hits else 0)
รันก่อนและหลังการย้าย:
$ python verify.py src/
src/render.py:4: from aspose.pydrawing import Color, Point
src/render.py:11: import aspose.pydrawing
src/render.py:12: reference to aspose.pydrawing
3 reference(s) left
$ python migrate.py src/ --write
wrote src/render.py
$ python verify.py src/
migration complete
สุดท้าย, รันการทดสอบ smoke ที่เรียกใช้ชนิดที่ย้าย:
import aspose.slides as slides
with slides.Presentation() as presentation:
slide = presentation.slides[0]
shape = slide.shapes.add_auto_shape(slides.ShapeType.RECTANGLE, 50, 50, 200, 100)
shape.fill_format.fill_type = slides.FillType.SOLID
shape.fill_format.solid_fill_color.color = slides.Color.red
presentation.save("smoke.pptx", slides.export.SaveFormat.PPTX)
print("OK")
ลำดับการย้ายที่แนะนำ
- บันทึกฐานข้อมูล. รันการทดสอบของคุณบนเวอร์ชันปัจจุบันและเก็บผลการเรนเดอร์อ้างอิง. สิ่งนี้ทำให้คุณแยกข้อผิดพลาดการย้ายจากความแตกต่างของการเรนเดอร์ในภายหลัง.
- ชมภาพรวมการย้าย. รันสคริปต์ใดสคริปต์หนึ่งโดยไม่ใช้
--writeและตรวจสอบรายการไฟล์ที่มันจะเปลี่ยน. - นำไปใช้และตรวจสอบ. รันด้วย
--write --backup, จากนั้นสคริปต์ตรวจสอบและการทดสอบ smoke. - เปรียบเทียบการเรนเดอร์ด้วยทอลแรนซ์. การย้ายไปยัง .NET 6 อาจทำให้เกิดความแตกต่างเล็กน้อยในข้อความและเอฟเฟกต์. ใช้วิธีเปรียบเทียบแบบเกณฑ์แทนการตรวจสอบไบต์ต่อไบต์.
- ลบไฟล์สำรอง. เมื่อผลลัพธ์ได้รับการยืนยัน, ลบไฟล์
.bak:find . -name '*.py.bak' -deleteบน Linux และ macOS, หรือGet-ChildItem -Recurse -Filter *.py.bak | Remove-Itemบน Windows.
สนับสนุนทั้งสองเวอร์ชันในฐานโค้ดเดียว
หากคุณต้องการรันกับ 26.7 และ 26.8 จากแหล่งเดียวกัน:
try:
from aspose.slides import Color, Point, Rectangle # 26.8 และต่อไป
except ImportError:
from aspose.pydrawing import Color, Point, Rectangle # 26.7 และก่อนหน้า
สิ่งที่ไม่เปลี่ยนแปลง
- ชื่อ, อาร์กิวเมนต์, และพฤติกรรมของ primitive ที่ย้าย
- ส่วนที่เหลือของ API
aspose.slides - การให้ลิขสิทธิ์และวิธีการใช้ไฟล์ลิขสิทธิ์
- รูปแบบไฟล์และพฤติกรรมการบันทึกและโหลด
- ความต้องการของระบบบน Windows และ macOS
- การไม่มีการติดตั้ง .NET แยกต่างหาก - runtime ยังคงถูกรวมไว้