संस्करण 26.8 में नए Python‑to‑.NET इंजन में प्रवास करें
परिचय
संस्करण 26.8 Python को .NET से जोड़ने वाले इंजन को प्रतिस्थापित करता है। ड्राइंग प्रिमिटिव्स aspose.slides मॉड्यूल में स्थानांतरित किए गए हैं।
यदि अपडेट के बाद आपको समस्याएँ आती हैं तो सीधे मेरे पास त्रुटि है पर जाएँ।
ड्राइंग प्रिमिटिव्स 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
आयात त्रुटि को ठीक करें
पहले कॉलम में अपना ट्रेसबैक खोजें।
| त्रुटि | कारण | सुधार |
|---|---|---|
AttributeError: module 'aspose.pydrawing' has no attribute 'Color' (या Point, Rectangle, आदि) |
पैकेज 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 किसी रंग, बिंदु या आकार तर्क पर |
aspose.pydrawing से बना मान नए API को पास किया गया है |
aspose.slides से भी वही मान बनाएं |
अपना कोड अपडेट करें
क्योंकि aspose.pydrawing में केवल सात स्थानांतरित प्रकार ही बचते हैं, स्थलांतरण केवल मॉड्यूल के नाम बदलने के बराबर है। सभी आयात रूप इस एकल रीनेम से कवर हो जाते हैं, जिसमें उपनाम भी शामिल हैं:
# पुराना कोड
import aspose.pydrawing as drawing
color = drawing.Color.red
# संस्करण 26.8 - उपनाम काम करता रहता है
import aspose.slides as drawing
color = drawing.Color.red
यह किसी भी स्कोप में मान्य है, यहाँ तक कि फ़ंक्शन बॉडी के भीतर भी, क्योंकि उपनाम उसी स्थान पर बंधा रहता है जहाँ पहले बंधा था। एक ही कमी यह है कि नाम थोड़ा भ्रामक है, इसलिए स्पष्ट इरादा दर्शाने पर विचार करें:
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 न पास करने पर परिवर्तन का पूर्वावलोकन दिखाती है। परिवर्तन को लिखने के लिए --write और बैकअप बनाने के लिए --backup जोड़ें। इसे कोई भी नाम दें — उपयोग संदेश रन‑टाइम पर नाम लेता है।
"""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-आधारित स्क्रिप्ट के साथ बदलें
बड़े कोड बेस के लिए अनुशंसित। यह स्क्रिप्ट वही रीनेम करती है, लेकिन पहले प्रत्येक फ़ाइल को पार्स करती है, इसलिए स्ट्रिंग, टिप्पणी या डॉकस्ट्रिंग में मौजूद घटनाएँ नहीं छूती।
क्योंकि यह मॉड्यूल को इन‑प्लेस रीनेम करता है और उपनाम को अपरिवर्तित छोड़ता है, सभी आयात रूप बिना विशेष मामलों के संभाले जाते हैं: 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):
# import aspose.pydrawing [as X] / from aspose.pydrawing import ...
# मॉड्यूल नाम को स्थान पर ही पुनःनामित किया जाता है, इसलिए कोई भी उपनाम पहले की तरह बंधा रहेगा।
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)))
# Any expression referring to the module, including bare `fn(aspose.pydrawing)`.
# किसी भी अभिव्यक्ति जो मॉड्यूल को संदर्भित करती है, जिसमें सरल `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")
दोनों स्क्रिप्ट आईडेम्पोटेंट हैं: माइग्रेटेड कोड पर फिर चलाने से कुछ नहीं बदलता।
स्थलांतरण की जाँच करें
एक टेक्स्ट खोज दिखाती है कि क्या कुछ बचा है:
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
अंत में, एक स्मोकी टेस्ट चलाएँ जो स्थानांतरित प्रकारों को एक्सरसाइज़ करे:
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के साथ चलाएँ, फिर सत्यापन स्क्रिप्ट और स्मोकी टेस्ट चलाएँ। - रेंडर की तुलना सहनशीलता के साथ करें। .NET 6 बिल्ड में बदलाव के कारण टेक्स्ट और इफ़ेक्ट्स में छोटे अंतर आ सकते हैं। बाइट‑फॉर‑बाइट तुलना के बजाय थ्रेसहोल्ड‑आधारित तुलना का उपयोग करें।
- बैकअप हटाएँ। परिणाम की पुष्टि होने के बाद
.bakफ़ाइलें हटाएँ: Linux/macOS परfind . -name '*.py.bak' -delete, Windows परGet-ChildItem -Recurse -Filter *.py.bak | Remove-Item।
एक कोड बेस में दोनों संस्करणों का समर्थन करें
यदि आपको समान स्रोत से 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 और पहले
जो नहीं बदला
- स्थानांतरित प्रिमिटिव्स के नाम, तर्क और व्यवहार।
aspose.slidesAPI का शेष हिस्सा।- लाइसेंसिंग और लाइसेंस फ़ाइल लागू करने का तरीका।
- फ़ाइल फ़ॉर्मेट और सहेजने‑लोड करने का व्यवहार।
- Windows और macOS पर सिस्टम आवश्यकताएँ।
- अलग .NET इंस्टॉलेशन की अनुपस्थिति — रन‑टाइम अभी भी बंडलेड है।