استوديو رموز QR
رمز QR أقل قطع البرمجيات بريقًا في ما ستفعله يومًا، والأكثر بقاءً: مطبوعة على ملصق أو تذكرة، يجب أن تنجو من الضبابية والاتساخ وهاتف مرفوع بزاوية غير مجاملة. على أدوات QR الحقيقية موازنة ثلاثة أشياء معًا ، مقدار البيانات التي تحشوها، ومقدار التلف الذي تنجو منه، وما إذا كانت تبدو علامةً تجاريةً لا مربعًا أسود. يبني هذا المشروع استوديو صغيرًا يفعل الثلاثة: يولّد رمزًا من نص، ويعيد تلوينه، ويدمغ شعارًا في وسطه، وينتج مجلدًا كاملًا من صف جدول بيانات لكل رمز ، ثم يتحقق من المجموعة بقراءة كل مصفوفة من القرص والتحقق من أنها تطابق ما طلبته.
يفترض هذا Python 101 ، إدخال/إخراج الملفات، والسلاسل، والدوال. لا شيء بعده: لا ويب، ولا كاميرا، ولا APIs. هذا اختياري وغير مُقيَّم؛ راجع مشاريع من العالم الحقيقي للاطلاع على القائمة الكاملة.
🎯 ما ستفعله
- أنشئ أول رمز QR من سلسلة نصية واحفظه PNG يمكنك مسحه فعلًا.
- أعد تلوين رمز وضمّن شعارًا مركزيًّا بـ Pillow ، “الاستوديو” في استوديو QR.
- قارن مستويات تصحيح الأخطاء الأربعة وراقب ميزانية البيانات تتقلص كلما كبرت الحماية.
- أنشئ رموزًا مجمعةً من CSV، واحدًا لكل صف، في مجلد.
- تحقّق من المجموعة بقراءة كل صورة محفوظة ومقارنتها، مصفوفةً بمصفوفة، بمرجع مولد حديثًا.
أين تُشغّل هذا
محليًا باستخدام uv هو المسار الأساسي ، العائد ملفات .png حقيقية على القرص (امسح واحدًا بهاتفك)، وحلقة المجموعة من CSV إلى مجلد عمل مسارات ملفات فعلًا. الاعتمادان (qrcode، pillow) يثبّتان بنظافة عبر uv add.
GitHub Codespaces التجربة نفسها: افتح codespaces.new/abderrahim-lectures/python-data-analysis-course وتُشغَّل الأوامر نفسها في نافذة متصفح، مع PNG المولّد جالسًا في شجرة الملفات للتنزيل.
Google Colab وKaggle Notebooks وBinder يشغّلون خط الأنابيب كله بأمانة ، توليد الكود، وإعادة التلوين، ودمغ الشعار، والتحقق المجمع كلها حسابات صور محلية بلا مفاتيح ولا GPU ، ويمكن للدفتر حتى عرض PNG المولّد بسطر inline فترى المصفوفة قبل أن تحفظها يومًا. الشيء الوحيد الذي لا يحدث في دفتر أن ترفع هاتفك إلى الشاشة ، وهو تحديدًا فحص المسح الذي سترغب في فعله محليًا لحظة هبوط الملفات.
الإعداد
كل ما تحتاجه قبل عرض أول مربع أسود: uv، والمكتبتان، وصورة شعار صغيرة لتضمينها.
ثبّت uv والاعتمادات
macOS / Linux (الطرفية):
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
أغلق طرفيتك وأعد فتحها، ثم:
uv --version
mkdir qr-code-studio && cd qr-code-studio
uv init --bare
uv add qrcode pillow
أنشئ شعارًا صغيرًا
تحتاج حسابات صور Pillow لاحقًا صورة فعلية لدمغها. ولّد شعار 60×60 PNG نقطة على أبيض بـPython نفسه ، دون أداة تصميم:
# make_logo.py
from PIL import Image
img = Image.new("RGB", (60, 60), "white")
for y in range(15, 45):
for x in range(15, 45):
if abs(x - 30) + abs(y - 30) < 16:
img.putpixel((x, y), (30, 144, 255))
img.save("logo.png")
print("logo.png written")
uv run python make_logo.py
uv run python -c "import qrcode; print('qrcode ready')"
✅ قائمة التحقق
- ✅
uv --versionيطبع رقم إصدار؛ وqrcodeوpillowمثبّتان عبرuv add. - ✅
logo.pngموجودة (60×60، معيّن أزرق على أبيض). - ✅
uv run python -c "import qrcode"ينجح.
الخطوة 1: أنشئ واحفظ أول QR لك
الاستوديو كله مبني على كائن واحد: qrcode.QRCode. تسلّمه البيانات، ويعرض .make_image() المصفوفة، ويُرجع Pillow صورة حقيقية يمكنك .save() بها. لحظة “كتبت كودًا تقرؤه كاميرا هاتف” هي كل دافع لهذه الخطوة.
1.1 اصنع رمزًا قابلًا للمسح
# studio.py
import qrcode
def make_qr(data: str, out_path: str, **kwargs) -> None:
qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_M,
box_size=10, border=4, **kwargs)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
img.save(out_path)
print(f"saved {out_path} ({img.size[0]}x{img.size[1]}px)")
if __name__ == "__main__":
make_qr("https://example.com/course/lesson-1", "lesson1.png")
version=1 مع fit=True مفاوضة “أصغر رمز يناسب”: تبدأ المكتبة بالإصدار 1 (21×21 وحدة) وتنمو فقط كما يقتضي البيانات، فيحصل عنوان قصير على رمز متراص قابل للمسح لا رمزًا محشوًّا. box_size بكسلات كل وحدة، وborder عرض منطقة الهدوء بوحدات ، وكلاهما يتحكم مباشرة في مقروئية المسافة البعيدة، وستسمع الهاتف يتذمّر صاخبًا إذا هبط border إلى 0.
👟 تلميح البداية : شغّل الصانع، ثم امسح lesson1.png فعلًا بكاميرا هاتفك ، يجب أن يفتح الرابط متصفحًا. تُغلق الحلقة في هاتف، لا في طرفية.
🎯 الناتج المتوقع : saved lesson1.png (290x290px) ، (21 + 2×4) × 10 بكسلات لرمز إصدار 1 مع حدود ، والملف يُمسح إلى العنوان بالضبط.
🩹 إذا لم يعمل : إذا كان الملف المحفوظ أسود على أبيض لكن هاتفك لا يقرؤه، فالحد صغير جدًّا أو الصورة المصغرة أصغر من شاشتك ، border=4 حد أدنى بالوثيقة؛ جرب 8. إذا قال ValueError “data too long for version 1”، فـfit=True يُتجاهل أو يُحذف ، مع fit=True تنمّي المكتبة الإصدار؛ وبدونها يخطئ البيانات الزائدة الحجم.
1.2 تحقّق من التوليد
✅ قائمة التحقق
- ✅
lesson1.pngموجودة، و290×290بكسل، وكاميرا هاتف تفكّ شفرتها إلى العنوان بالضبط. - ✅ خلفية
uint8-بيضاء، ووحدات سوداء ، رمز عالي التباين نظيف. - ✅ صنع البيانات نفسها مرتين ينتج ملفين متساويي الحجم تتطابق شبكتا بكسلاتهما (ستؤتمت الخطوة 5 هذا تحديدًا).
🤔 سؤال (أسئلة) سقراطي(ة)
- يجعل
fit=Trueالمكتبة تكبّر الكود حتى تناسب البيانات. ما تكلفة رمز نما إلى الإصدار 40 مقابل الذي بقي عند الإصدار 1 ، وراء البكسلات، فكّر في مسافة المسح (تصغر الوحدات) ولماذا “الحد الأدنى من الإصدار” هو الافتراضي الصحيح؟ - منطقة الهدوء
borderمفروضة بالوثيقة، ومع ذلك تضبطها أدوات المبتدئين على 0 روتينيًّا. تنبّأ بما يفعله الماسح عندما يختفي الحد ، وأيَّ الاثنين (بيانات أم مساحات بيضاء) يُسمح لنتيجة مفكوكة بالفشل عليه؟
الخطوة 2: أعد التلوين وادمغ شعارًا
جزء “الاستوديو”. تتسامح رموز QR مع إعادة التنسيق بسبب تصحيح الأخطاء: أنماط المحددات (مربعات الزوايا الكبيرة الثلاث) يجب أن تبقى عالية التباين، لكن وحدات البيانات في الوسط فيها تكرار، ولدى Pillow بالضبط البنيات الأولية لاستغلاله ، إعادة التلوين عبر fill_color/back_color، ثم لصق شعار في المنطقة المركزية الآمنة.
2.1 أعد التلوين وضمّن
# studio.py (continued)
from PIL import Image
def make_branded(data: str, out_path: str, logo_path: str = "logo.png",
fill=(20, 90, 220), back=(255, 255, 255)) -> None:
qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10, border=4)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill_color=fill, back_color=back).convert("RGB")
logo = Image.open(logo_path).resize((img.size[0] // 5, img.size[1] // 5))
cx, cy = img.size[0] // 2, img.size[1] // 2
img.paste(logo, (cx - logo.width // 2, cy - logo.height // 2))
img.save(out_path)
if __name__ == "__main__":
make_branded("https://example.com/landing", "landing-branded.png")
قرارا تصميم يجعلان الرمز المروَّج قابلًا للمسح لا زخرفًا: error_correction=H (الأعلى ، يمكن ثلُث الوحدات أن تتضرر ويظل الكود يفكّ، وهي الميزانية التي يمتصها الشعار)، وسقف الشعار عند خُمس الصورة (img.size[0] // 5)، ويبقي الدمغة داخل المركز زائد التكرار وبعيدًا عن أنماط المحددات الثلاثة كلها في الزوايا. img.paste(logo, ...) هو العلامة-في-الصندوق بأكملها ، متمركزة بطرح نصف أبعاد الشعار من منتصف النقطتين.
👟 تلميح البداية : شغّلها، وافتح landing-branded.png، وامسح بهاتفك قبل تعديل الألوان ، معيّن أزرق على أبيض يجب أن يفكّ بنظافة. ثم ادفع fill من (20, 90, 220) إلى (250, 250, 250) (قرب-أبيض-على-أبيض) وارقب الهاتف يفشل؛ تلك التجربة تعلّم التباين أفضل من أي فقرة.
🎯 الناتج المتوقع : رمز 290×290 بتصحيح H مع شعار أزرق ≈58×58 في قلب المركز، ما يزال يفكّه كاميرا هاتف إلى عنوان الهبوط.
🩹 إذا لم يعمل : إذا كسر الشعار المسح، فأنت بمستوى تصحيح أدنى أو الشعار أكبر من خُمس ، كلاهما ينفق ميزانية تصحيح الأخطاء أبعد مما يغطيه H؛ ERROR_CORRECT_H مع سقف // 5 الزوج الآمن. إذا قرأ هاتفك الأزرق الغامق تباينًا منخفضًا، أبْقِ fill داكنًا وback فاتحًا ، الألوان شبه المتساوية فشل كاميرا هاتف الكلاسيكي.
2.2 تحقّق من الترويج
✅ قائمة التحقق
- ✅
landing-branded.pngتمسح إلى عنوان الهبوط مع الشعار حاضرًا. - ✅ أنماط المحددات الثلاثة في الزوايا اللَّم تُمس ، الشعار متمركز وصغير بما يكفي لتجنّبها.
- ✅ إعادة التلوين إلى غامق-على-فاتح تحافظ على الفكّ؛ وإلى أبيض-على-أبيض تكسره (وتعرفِ لماذا ، تباين الوحدات).
- ✅ تصحيح
Hمقصود: دون ميزانية التكرار، يكون الشعار نفسه لُبًّا غير قابل للمسح.
🤔 سؤال (أسئلة) سقراطي(ة)
- تكلفة الشعار ميزانية التكرار ، يغطي
Hتلف 30%. إذا طلب مصمم شعارًا يغطي ثلث الصورة بدل الخُمس، فماذا يحدث فعلًا ، أي وحدات محددة تُتلف، وهل أي زاوية آمنة؟ (تلميح: فكّر فيfinders.) - تصحيح
L(7%) يصنع رمزًا أكثف لنفس البيانات. متى تختارLعمدًا وتبتلع الهشاشة ، سمِّ سيناريو ملصق أو تذكرة حقيقيًّا حيث الصِّغَر يغلب المتانة؟
الخطوة 3: قارن مستويات تصحيح الأخطاء
يبدو “تصحيح الأخطاء” ثنائيًّا، لكنه مؤشر بأربعة مواضع ، L، M، Q، H ، يبادل سعة البيانات بـالنجاة من التلف. تولّد هذه الخطوة الحمولة نفسها في المستويات الأربعة وتطبع الفرق: وحدات أقل لكل وحدة بيانات، أو أكثر بشكل صارخ، في تجربة واحدة قابلة للتكرار.
3.1 امسح المستويات
# studio.py (continued)
import qrcode.constants as C
LEVELS = {"L": C.ERROR_CORRECT_L, "M": C.ERROR_CORRECT_M,
"Q": C.ERROR_CORRECT_Q, "H": C.ERROR_CORRECT_H}
def sweep(data: str) -> None:
for name, code in LEVELS.items():
qr = qrcode.QRCode(version=None, error_correction=code, box_size=4, border=4)
qr.add_data(data)
qr.make(fit=True)
print(f"{name}: version {qr.version} matrix {qr.modules_count}x{qr.modules_count}")
if __name__ == "__main__":
sweep("https://example.com/course/lesson-1")
version=None يؤجّل اختيار الحجم إلى fit=True، فيجيب المسح عن سؤال واحد لكل مستوى: كم يجب أن تكون المصفوفة لهذه الحمولة بالضبط عند هذا الحظر؟. عنوان قصير يبقى إصدار 1 عند L وM وQ، وH فقط تقفز ، خلاصة التجربة أن البيانات المعتدلة تكاد لا تدفع ثمن الصعود، بينما حمولة 1000 حرف ستقسّم المستويات بدرامية.
👟 تلميح البداية : شغّل المسح، وأعد تشغيله بسلسلة بيانات طويلة ("x" * 400) ، يقفز عمود الإصدار مرئيًّا. التشغيلان متتاليين هما الدرس كله.
🎯 الناتج المتوقع : أربعة أسطر ، للعنوان القصير، إصدارات مثل 1 / 1 / 1 / 2 (×2 عند H)؛ لـ400 حرف، إصدارات أكبر ملحوظًا ومختلفة لكل مستوى، مع L الأرخص وH الأغلى بالوحدات.
🩹 إذا لم يعمل : إذا أظهرت الأسطر الأربعة الحجم نفسه، فـversion=None + fit=True لا ينمّي ، تحقق أنك مررت version=None وأبقيت fit=True (يجب أن تسعّر المكتبة الكود بنفسها). إذا أخطأ ثقل حمولة طويل جدًّا، فتتجاوز السلسلة سعة الإصدار 40 ، ليس ذلك خللًا، إنه سقف وثيقة QR الصلب، وهو يعيش عند 3 كيلوبايت.
3.2 تحقّق من المسح
✅ قائمة التحقق
- ✅ العنوان القصير ينتج ≤2 صفوف شبه متطابقة؛ و400 حرف ينتج 4 أحجام مميزة.
- ✅
Lدائمًا أصغر-أو-يساوي وHأكبر-أو-يساوي في أبعاد المصفوفة. - ✅ يمكنك إعادة صياغة المفاضلة في جملة واحدة: حماية أكثر = وحدات بيانات أقل لكل مساحة = رموز أكبر / حمولة أقل لكل إصدار.
🤔 سؤال (أسئلة) سقراطي(ة)
- قمنا بالقياس. الآن تنبّأ: عند أي حجم حمولة يتوقف
LوHعن الاختلاف بإصدار كامل، وما الذي يكلفه “نفس الكود، أدرع أفضل” في مسافة المسح، بالضبط؟ - إذا كان لملصق بريدي 5 مم للرمز وعليه النجاة من رذاذ مطر، فأي مستوى تختار ، وما الذي يدفعك دون ذلك الاختيار حتى وأنت تفضل غير ذلك؟
الخطوة 4: أنتِج مجمعًا من CSV
واحدًا-تلو-الآخر عرض توضيحي؛ CSV خط إنتاج. كل صف حمولة رمز، ووظيفة الاستوديو تحويل codes.csv إلى مجلد من ملفات .png فريدة في مرحلة واحدة ، نفس انضباط “ملف البيانات يقود الأداة” الذي يحوّل أي سكربت لمرة واحدة إلى عمل دائم.
4.1 ولّد مجلدًا من جدول بيانات
أنشئ codes.csv:
label,payload
course1,https://example.com/course/lesson-1
course2,https://example.com/course/lesson-2
course3,https://example.com/course/lesson-3
ticket-A1,https://example.com/tickets/A1
# studio.py (continued)
import csv
from pathlib import Path
def batch(csv_path: str, out_dir: str = "out") -> None:
out = Path(out_dir)
out.mkdir(exist_ok=True)
with open(csv_path, newline="") as f:
for row in csv.DictReader(f):
make_qr(row["payload"], str(out / f"{row['label']}.png"))
print(f"batch done -> {len(list(out.glob('*.png')))} pngs in {out}/")
if __name__ == "__main__":
batch("codes.csv")
يسلّم csv.DictReader كل صف كقاموس مفاتيحه ترويسته ، فـrow["payload"] يقرأ بنظافة، والعمود المفقود يثير KeyError صاخبًا باسم العمود، لا حمولة None تولّد أربعة مربعات سوداء. تصبح التسمية اسم الملف، وهو تعاقد المجموعة كله: صف CSV واحد لكل مخرج، وصفر تسمية يدوية.
👟 تلميح البداية : شغّل المجموعة وls out/ ، أربعة ملفات course1.png … ticket-A1.png. ثم اكسر صف CSV عمدًا (أسقط عمود الحمولة) وارقب KeyError يسمّي العمود ، ذلك الفشل الصاخب ميزة.
🎯 الناتج المتوقع : batch done -> 4 pngs in out/، كل ملف مسمّى تمامًا كتسمية CSV الخاصة به، وكلٌّ يمسح إلى حمولته.
🩹 إذا لم يعمل : إذا اكتسبت أسماء الملفات مسافة خاتمة (course1 .png)، فعمود تسمية الـCSV فيه مسافات ، يمرر csv.DictReader النص الخام؛ جرّد في batch (row["label"].strip()) عند المصدر. إذا اصطدمت تسميات مكررة، فيستبدل الصف الثاني الأول بصمت ، قرّر بين فحص صاخب بنمط KeyError أو تحذير استبدال؛ فقدان البيانات الصامت ليس الهدف أبدًا.
4.2 تحقّق من المجموعة
✅ قائمة التحقق
- ✅ أربع PNG، واحدة لكل صف، كلّها تمسح إلى حمولاتها المميزة.
- ✅ إزالة صف CSV يزيل PNG الخاص به في التشغيل التالي ، المجموعة مشتقة من الملف، لا تُدار يدويًّا.
- ✅ العمود المفقود يثير
KeyErrorيسمّي العمود، لا مربع حمولة-Noneصامت.
🤔 سؤال (أسئلة) سقراطي(ة)
- التسمية اسم الملف. ما خطر التزامن أو الاستبدال إذا حمل CSV صفّين بنفس التسمية ، وهل “آخر صف يكسب” مقبول لجولة ملصقات، أم تحتاج الأداة للفشل صاخبًا؟ انتقِ جانبًا مع سبب.
- أسماء ملفات التسمية من جدول بيانات، ف
ticket-A1جيد لكن../ticket-A1سيكتب خارج مجلد الإخراج. ما الفحص أحادي السلسلة (in Path(...).name) الذي يحمي المجلد ، وهل استخدامه يشعرك بأمان أكبر تجاه المسارات المدفوعة بـCSV عمومًا؟
الخطوة 5: تحقّق من المجموعة
استوديو يطبع إلى ملف ويمشي نصف أداة فقط؛ النصف الآخر التحقق. تمسح خطوط الإنتاج الحقيقية كل تسمية عائدة. لا ماسح عندنا، لكن عندنا ثاني أفضل شيء: أعد توليد كل حمولة من الصفر كمرجع مصفوفة وطابقه، وحدةً بوحدة، ضد الصورة المؤرشفة ، إذا اتفق الاثنان، فالملف على القرص هو بالضبط الكود الذي طلبناه.
5.1 أعد التحقق من كل رمز محفوظ
# studio.py (continued)
def matrix_of(data: str, box: int = 10) -> list[list[int]]:
qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_M,
box_size=box, border=4)
qr.add_data(data)
qr.make(fit=True)
return qr.modules
def pixels_as_modules(img: Image.Image) -> list[list[int]]:
g = img.convert("L")
w, h = g.size
# 10px per module per box_size=10 (plus the 4-module border, which we keep dark/light)
return [[0 if g.getpixel((x, y)) < 128 else 1 for x in range(w)] for y in range(h)]
def verify(data: str, saved_path: str) -> bool:
expected = matrix_of(data)
actual = pixels_as_modules(Image.open(saved_path))
expected_small = [[expected[y][x] for x in range(len(expected))] for y in range(len(expected))]
ok = True
for y in range(min(len(expected_small), len(actual))):
for x in range(min(len(expected_small[y]), len(actual[y]))):
if expected_small[y][x] != actual[y][x]:
ok = False
print(f"{'OK ' if ok else 'BAD'} {saved_path}")
return ok
if __name__ == "__main__":
verdicts = [
verify("https://example.com/course/lesson-1", "out/course1.png"),
verify("https://example.com/tickets/A1", "out/ticket-A1.png"),
]
print("all verified" if all(verdicts) else "some failed")
qr.modules المصفوفة الخام ، قائمة قوائم من منطقيات، وحدة 0-أو-1 للكود كله ، وتعيد verify توليدها حديثًا من الحمولة، المدخل الوحيد الذي يُوثق به. يحوّل pixels_as_modules كل بكسل محفوظ إلى 0/1 ويقارن خليةً بخلية: تطابق تام يعني أن الملف المؤرشف يشفّر بالضبط ما طلبه الـCSV. المقايضة التصميمية صريحة ، علامة مائية، أو إعادة تلوين، أو شعار سيفجرّ هذا الفرق الصارم، فالتحقق-مع-التعديلات هو قرارك الأول “متى يكون عدم التطابق مقبولًا؟” المسجّل في كود.
👟 تلميح البداية : تحقّق من الرمزين العاديين أولًا (كلاهما OK)، ثم وجّه verify إلى landing-branded.png وارقبه يفشل عن قصد ، الشعار تلف متوقع، والفرق الصارم يقيس انتباهك للفرق، وهو المهارة الحقيقية.
🎯 الناتج المتوقع : OK .../out/course1.png، OK .../out/ticket-A1.png، وall verified ، مع انقلاب verify("https://example.com/landing", "landing-branded.png") إلى BAD لأن الشعار يغيّر وح ًدات المركز.
🩹 إذا لم يعمل : إذا عاد كل شيء BAD، فمسار الاستيراد أو افتراضات box_size معطوبة ، يجب أن يستخدم matrix_of نفس box_size والحد اللذين وُلِّدت بهما الملفات، وإلا فإعادة تحجيم شبكة البكسلات تنسّق بشكل خاطئ بصمت. إذا أثار verify OSError، فالملف المحفوظ ليس صورة مقروءة ، كتبتها المجموعة باسم مختلف؛ اطبع قائمة out/.
5.2 تحقّق من المُتحقِّق
✅ قائمة التحقق
- ✅ رمزا المجموعة العاديان يتحققان
OKمقابل مصفوفات معاد توليدها حديثًا. - ✅ يبلغ الرمز المروَّج
BADعن قصد ، الفرق الصارم يلتقط الشعار، بالتصميم. - ✅ إعادة توليد ملف من الـCSV نفسه وإعادة التحقق تنتج
OK، الحتمية قائمة. - ✅ يمكنك التعبير عما لا يستطيع
verifyفحصه (لن يفكّ النص؛ يقارن وحدات بصرية) ، ولماذا ذلك حدّ وميزة في آن.
🤔 سؤال (أسئلة) سقراطي(ة)
- يُثبت المُتحقِّق “الصورة تطابق الكود المولد حديثًا لهذه الحمولة” ، لكن “مولّد حديثًا” و”صحيح” شيء واحد فقط إذا كانت المكتبة موثوقة. ماذا يضيف فحص ثانٍ مستقل كليًّا (مرحلة فكّ حقيقية عبر مكتبة فكّ، أو مولّد QR ثانٍ) وراء ما يمكن أن يدّعيه فرقك؟
- يعلّم فرق البكسل الصارم لدينا شعار العلامة فشلًا. أعد كتابة قاعدة القبول في جملة واحدة ، “OK إذا اختلفت فقط منطقة X-في-Y الداخلية، وإلا BAD” ، وسمِّ ما يتغير في خط الأنابيب عندما تكون تلك هي السياسة بدلًا من ذلك.
⚠️ مآزق شائعة
- حد صفري، رمز غير مقروء. منطقة الهدوء
border=4جزء من وثيقة QR لا زخرفة ، رمز محفوظ بـborder=0يقتل المسح-عبر-الهاتف غالبًا. أبقِه ≥4 وحدات وتذكّر أن الحد يضخّم حجم البكسل ((modules+2·border)·box_size). - تصحيح أخطاء منخفض + شعار. يترك
Lميزانية تلف 7%؛ شعار يحرق المركز يتجاوزها فورًا. التركيبة المهتمة بالشعارH+ دمغة ≤ خُمس حجم الصورة ، خطأ في أيٍّ منهما يصنع QR جميلًا لا يُمسح. - تصادم أسماء ملفات المجموعة يستبدل بصمت. صفّان CSV بنفس التسمية ينتج أحدهما الملف الباقي ويختفي الآخر بلا كلمة. التسميات المكررة إما خطأ بيانات يستحق
ValueErrorصاخبًا أو سياسة متعمدة؛ الاستبدال الصامت الخيار الوحيد الخطأ دائمًا. - فضاءات CSV تسمّم أسماء الملفات.
label(مسافة قبل السطر الجديد) ينتجfile .pngوفحصًا “يعمل” بينما المنتج يبدو خطأ. جرّد كل حقل عند القراءة، في موضع واحد، ولا تدع خلية خام تملك مسارًا يومًا. - الثقة بالفرق فوق المفكّك. فرق مصفوفة صارم يثبت التناسق الذاتي مع مكتبة واحدة ، لن يلتقط خلل مكتبة، أو فرق شفّرة دقيق، أو اختيار ألوان معادٍ للماسح. كومة التحقق الصادقة فرقك الخلية-بخلية (سريع، بلا اتصال) زائد مسح كاميرا هاتف حقيقي واحد على الأقل قبل أن يبحر تشغيل.
ما بنيته للتو
استوديو QR يعمل: توليد رمز واحد، وإعادة تلوين ودمغ شعار، ومسح تصحيح أخطاء بأربعة مستويات، وإنتاج دفعات مدفوع بـCSV، ومُتحقِّق بلا اتصال يطابق كل رمز مؤرشف ضد مرجع مولد حديثًا. كاميرا هاتفك اختبار القبول لكل ملف ينتجه، وحيلة “أعد توليد المرجع، طابق الأرشيف” عادة تحقق قابلة للنقل فعلًا ، الفكرة نفسها وراء فحوصات البناء القابل للتكرار ومجموعات اختبارات الصور الذهبية. الاستوديو صغير بما يكفي لقراءته كاملًا، وكبير بما يكفي ليهمس: هذه هي هيئة شحن أداة مساعدة.
شغّل نسخة أكمل دون أي إعداد محلي
examples/qr-code-studio/ في مستودع الدورة يضمّ وحدة الاستوديو وcodes.csv وlogo.png ودفترًا يولّد ويعيد اللون ويبنئ ويجمع ويتحقق inline. استنسخه، أو افتح المستودع كاملًا في GitHub Codespaces، وارقب PNGs تعرض مباشرة في الدفتر.
إلى أين تذهب من هنا
- دعم الفكّ (اختياري):
pip install opencv-python-headlessواستخدمcv2.QRCodeDetector().detectAndDecodeلدورة حقيقية كاملة ، يحصل مُتحقِّقك على إجابات “هل ينجو النص؟” صادقة، لا مساواة بكسل فقط. - علم
--style:--fill "#1f4fa3" --logo mark.png --level H، فيكون تجميعك قابلًا للتكرار من إعداد سطر أوامر بدل إعادة كتابته لكل تشغيل. - حمولات Wi-Fi وvCard: ولّد سلاسل
WIFI:T:WPA;S:net;P:key;;وMECARDفيصنع الاستوديو ملصقات “انضم للواي فاي” أو “احفظ جهة اتصال” قابلة للمسح من الخط الأنابيب نفسه. - فحص الدمج: وسّع المُتحقِّق ليقبل فرق المنطقة الداخلية فقط، فتتحقق الرموز المروَّجة أيضًا ، خطاف سقراط في الخطوة 5 مصنوعًّا كودًا.
شارك مشروعك مع الصف
هل بنيت شيئًا تفخر به ، دفعة رموز قرأها ماسح لوحة شريات فعلًا، جولة ملصقات مرموقة نجت من هاتفك؟ examples/student-projects/ معرض لمشاريع قدّمها طلاب آخرون، ويشرح README إضافة مشروعك عبر طلب سحب (pull request) من البداية للنهاية: التفرع، وفرع العمل، والالتزام، وفتح PR. لا يُفترض أي خبرة سابقة بـ git.
مرحبًا بك في كتابة Python خارج المتصفح. 🎓
أكمل كل خطوة ثم حدد المشروع كمكتمل لجمع نقاطه.