Migration zur neuen Python-zu-.NET-Engine in Version 26.8
Einführung
Version 26.8 ersetzt die Engine, die Python mit .NET verbindet. Die Zeichenprimitive wurden in das Modul aspose.slides verschoben.
Springen Sie direkt zu Ich habe einen Fehler, wenn Sie nach dem Upgrade Probleme haben.
Zeichenprimitive nach aspose.slides verschoben
| Typ | Vor 26.8 | 26.8 und später |
|---|---|---|
| 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 |
Diese sieben Typen stellten den gesamten verbleibenden Inhalt von aspose.pydrawing dar. Sobald Sie sie umgeleitet haben, muss Ihr Code überhaupt nicht mehr auf aspose.pydrawing verweisen, und jeder Import davon kann entfernt werden. Das erleichtert auch die Überprüfung – siehe Migration überprüfen.
Legacy-Code:
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)
Version 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)
Die from-Import-Form ändert sich auf dieselbe Weise:
# Legacy-Code
from aspose.pydrawing import Color, Point
# Version 26.8
from aspose.slides import Color, Point
Importfehler beheben
Suchen Sie die Traceback-Ausgabe in der ersten Spalte.
| Fehler | Ursache | Lösung |
|---|---|---|
AttributeError: module 'aspose.pydrawing' has no attribute 'Color' (or Point, Rectangle, and so on) |
Das Paket ist 26.8, der Code verweist noch auf das alte Modul | Aktualisieren Sie Ihren Code |
ImportError: cannot import name 'Color' from 'aspose.pydrawing' |
Dasselbe Problem, from-Import-Form |
Aktualisieren Sie Ihren Code |
ModuleNotFoundError: No module named 'aspose.pydrawing' |
Das Modul und alle sieben seiner Typen wurden in aspose.slides verschoben |
Aktualisieren Sie Ihren Code, dann löschen Sie den aspose.pydrawing-Import |
ImportError: cannot import name 'Color' from 'aspose.slides' |
Der Code wurde migriert, aber das installierte Paket ist 26.7 oder älter | pip install --upgrade aspose.slides |
TypeError on a color, point, or size argument |
Ein Wert, der aus aspose.pydrawing erstellt wurde, wird an die neue API übergeben |
Erstellen Sie den Wert ebenfalls aus aspose.slides |
Ihren Code aktualisieren
Da aspose.pydrawing keinen anderen Inhalt als die sieben verschobenen Typen hat, besteht die Migration ausschließlich aus einer Umbenennung des Moduls. Jede Import-Form wird durch diese eine Umbenennung abgedeckt, einschließlich Aliasen:
# Legacy-Code
import aspose.pydrawing as drawing
color = drawing.Color.red
# Version 26.8 - der Alias funktioniert weiterhin
import aspose.slides as drawing
color = drawing.Color.red
Dies ist in jedem Gültigkeitsbereich gültig, auch innerhalb einer Funktionsdefinition, da das Alias genau dort gebunden bleibt, wo es vorher gebunden war. Der einzige Nachteil ist ein irreführender Name, daher sollten Sie die Absicht explizit machen:
import aspose.slides as slides
color = slides.Color.red
Wählen Sie den Ansatz, der zur Größe Ihres Codebestands passt.
Manuell ersetzen
Für einige Dateien suchen Sie nach aspose.pydrawing und ersetzen es durch aspose.slides, anschließend entfernen Sie alle nicht mehr benötigten Importe.
Mit einem Shell-Befehl ersetzen
Dies ist ein einfacher Textaustausch, daher werden auch Vorkommen in Zeichenketten und Kommentaren geändert. Beide Befehle schreiben eine .bak‑Kopie jeder geänderten Datei.
Linux:
grep -rlZ --include='*.py' 'aspose\.pydrawing' . \
| xargs -0 -r sed -i.bak 's/aspose\.pydrawing/aspose.slides/g'
Unter macOS verwenden Sie sed -i '' anstelle von sed -i.bak oder installieren GNU sed als 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
}
}
Um unter Linux oder macOS zurückzurollen:
find . -name '*.py.bak' -exec sh -c 'mv "$1" "${1%.bak}"' _ {} \;
Um unter Windows zurückzurollen:
Get-ChildItem -Recurse -Filter *.py.bak | ForEach-Object {
Move-Item $_.FullName ($_.FullName -replace '\.bak$', '') -Force
}
Mit einem Python‑Skript ersetzen
Die gleiche Umbenennung, portabel für Linux, macOS und Windows. Das Skript nimmt den Pfad als Argument und zeigt die Änderungen an, sofern nicht --write angegeben wird. Fügen Sie --backup hinzu, um eine .bak‑Kopie jeder geänderten Datei zu behalten. Speichern Sie es unter einem beliebigen Namen – die Hilfemeldung ermittelt den Namen zur Laufzeit.
"""Rename aspose.pydrawing to aspose.slides. Plain text replacement.
python <this script> src/ # preview
python <this script> src/ --write # apply
python <this script> src/ --write --backup # apply, keeping .bak copies
"""
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"))
Ein typischer Durchlauf sieht so aus:
$ 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
Der Pfad kann ein Verzeichnis sein, das rekursiv durchsucht wird, oder eine einzelne .py‑Datei.
Mit einem AST‑basierten Skript ersetzen
Empfohlen für größere Codebasen. Dieses Skript führt die gleiche Umbenennung durch, parsed jedoch zunächst jede Datei, sodass Vorkommen in Zeichenketten, Kommentaren oder Docstrings nie verändert werden.
Da es das Modul an Ort und Stelle umbenennt und Aliase unverändert lässt, wird jede Import-Form ohne Sonderfälle behandelt: import aspose.pydrawing, import aspose.pydrawing as X, from aspose.pydrawing import Color, from aspose.pydrawing import Color as C, mehrzeilige, geklammerte Importe, Importe innerhalb von Funktionen und das Modul, das als Wert übergeben wird. Es akzeptiert dieselben Flags --write und --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):
# import aspose.pydrawing [as X] / from aspose.pydrawing import ...
# Der Modulname wird an Ort und Stelle umbenannt, sodass jedes Alias wie zuvor gebunden bleibt.
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)))
# Jeder Ausdruck, der auf das Modul verweist, einschließlich eines nackten `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): # back to front keeps offsets valid
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")
Beide Skripte sind idempotent: Ein erneutes Ausführen auf migriertem Code ändert nichts.
Migration überprüfen
Eine Textsuche zeigt, ob noch etwas übrig ist:
grep -rn 'aspose\.pydrawing' --include='*.py' --exclude-dir=.venv .
Dies ist schnell, trifft jedoch auch in Zeichenketten und Kommentaren zu, sodass sauberer Code immer noch Treffer erzeugen kann. Für eine eindeutige Antwort benutzen Sie die nachstehende Prüfung. Sie meldet nur echte Code-Referenzen und beendet sich mit einem von Null verschiedenen Status, falls noch welche vorhanden sind, was sie als Build‑Gate nutzbar macht.
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)
Führen Sie es vor und nach der Migration aus:
$ 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
Abschließend führen Sie einen Smoke‑Test aus, der die verschobenen Typen verwendet:
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")
Empfohlene Migrationsreihenfolge
- Erstellen Sie eine Ausgangsbasis. Führen Sie Ihre Tests mit der aktuellen Version aus und behalten Sie Referenz‑Renderings. So können Sie Migrationsfehler später von Render‑Unterschieden trennen.
- Vorschau der Migration. Führen Sie eines der Skripte ohne
--writeaus und prüfen Sie die Liste der zu ändernden Dateien. - Anwenden und überprüfen. Führen Sie es mit
--write --backupaus, danach das Verifizierungs‑Skript und den Smoke‑Test. - Renderings mit Toleranz vergleichen. Der Umstieg auf das .NET‑6‑Build kann kleine Unterschiede in Text und Effekten erzeugen. Verwenden Sie einen Schwellenwert‑basierten Vergleich statt eines byte‑für‑byte‑Checks.
- Backups entfernen. Sobald das Ergebnis bestätigt ist, löschen Sie die
.bak‑Dateien:find . -name '*.py.bak' -deleteunter Linux und macOS oderGet-ChildItem -Recurse -Filter *.py.bak | Remove-Itemunter Windows.
Unterstützung beider Versionen in einem Code‑Bestand
Falls Sie sowohl gegen 26.7 als auch 26.8 aus derselben Quelle laufen lassen müssen:
try:
from aspose.slides import Color, Point, Rectangle # 26.8 und später
except ImportError:
from aspose.pydrawing import Color, Point, Rectangle # 26.7 und früher
Was sich nicht geändert hat
- Namen, Argumente und Verhalten der verschobenen Primitive.
- Der Rest der
aspose.slides‑API‑Oberfläche. - Lizenzierung und wie die Lizenzdatei angewendet wird.
- Dateiformate sowie das Speicher‑ und Ladeverhalten.
- Systemanforderungen unter Windows und macOS.
- Das Fehlen einer separaten .NET‑Installation – die Laufzeit ist weiterhin gebündelt.