اذهب إلى المحتوى

كيفية تحزيم وتوزيع تطبيقات بايثون


kinan mawed

إنّ كل مكتبات بايثون (مثل حزم التّطبيقات application packages) التي نقوم بتنزيلها باستخدام مدير الحزم package manager (مثل pip) يتمّ توزيعها باستخدام أداة مساعدة مُخصصة لهذا العمل، تقوم هذه الأدوات المساعدة بإنشاء توزيعات بايثون Python distributions والتي هي أساسا عبارة عن ملفات أرشيف مرقمة بإصدار ومضغوطة، تحتوي هذه الملفّات على جميع العناصر المتعلقة بما يتم توزيعه، مثل ملفات المصادر source files وملفات الموارد resource files.

python-package.thumb.png.438cd403af1da58

سنقوم في هذا الدرس بالتحدث عن الأدوات الضرورية للتوزيع، وسنتطرق إلى الخطوات الأساسية التي تسمح لنا بحزم المكتبات المفيدة الخاصة بنا، الوحدات modules، أو حتى التطبيقات applications والتي ستكون مفيدة لنا عند توزيع المشروع الخاص بنا على خادوم أو مشاركته على الإنترنت.

توزيعات وحزم بايثون

حتى ولو كنا قد عملنا قليلًا فقط مع بايثون، فنحن متآلفون مع مفهوم استخدام مدير الحزم (مثل pip ،easy_install) لتنزيل الوحدات والمكتبات (مثل هياكل تطوير التطبيقات application development frameworks) والتي يتم بعدها استيرادها واستخدامها لإنشاء واحدة جديدة.

تقوم أدوات إدارة الحِزَم هذه -والتي تعمل محليا- بالاتصال إلى مصدر بعيد source (مثل دليل حزم بايثون Python Package Index – PyPI) وتنفيذ الإجراء المطلوب (كالبحث والتنصيب).

تتكوّن طريقة توزيع تطبيق ما من تغليف الدليل directory الخاص به ببعض الملفّات الضّروريّة (مع القليل من الملفّات المُوصى بها)، تحديد العناصر المرتبطة (كالموارد resources والاعتماديات dependencies، إلخ) وإصدارها أو استخدامها في مكان آخر ببساطة.

ملاحظة: نشجعك بشدة على العمل على بيئات افتراضيّة لعزل تنزيلات بايثون، الوحدات والتطبيقات التي تعمل عليها.

1. حزم بايثون

الحزمة في بايثون هي تقنيا عبارة عن دليل قابل للاستيراد (باستخدام init__.py__ ) يحتوي على ملفات المصادر (كالوحدات)، ولا يجب الخلط بينها وبين حزم نظام التشغيل والتي هي تقنيًّا تطبيقات فعلية (مثل حزمة Debian)، ومع ذلك يجب أن نُلاحظ أنّ توزيعات بايثون في الواقع تدعى أيضًا بالحزم.

مثال على بنية الحِزمة:

package
 |
 |-- __init__.py

2. تطبيقات بايثون

على الرّغم من أنّه يُمكننا اعتبار أي شيء في بايثون كتطبيق وذلك ابتداء من ملف واحد وحتى مئات الملفات المُبعثرة عبر الحزم المُختلفة، فإنّ التطبيق في أغلب الحالات الواقعيّة يتكوّن من العديد من الوحدات والبعض من الاستيرادات الخارجيّة (من المكتبات).

مثال على بنية التّطبيق:

myapp
|
|-- __init__.py
|-- amodule.py
|-- anothermod.py
|__ tests
|     |
|     |-- __init__.py
|     |-- ..
|     |-- .
| ..

3. مكتبات وأدوات توزيع بايثون

نظرا لطبيعة شعبية لغة بايثون ووجود كميّة وافرة من مكتبات وتطبيقات الطرف الثالث third-party المكتوبة لأجلها فقد كان من الضّروري دوما إيجاد طريقة مُوحّدة وأبسط لتوزيعها، تُوجد العديد من المكتبات والأدوات المختلفة المُستخدمة لإنشاء توزيعات بايثون.

تمّ إنشاء مجموعة الأدوات المساعدة لتوزيع بايثون والتي تدعى distutils من أجل التعامل مع مهام التوزيع.

4. دليل حزم بايثون (Python Package Index (PyPI

دليل حزم بايثون أو PyPI هو مستودع مركزي (على الإنترنت Online) للمشاريع (توزيعات بايثون)، حيث تستخدم أدوات إدارة الحِزم مثل pip هذا المستودع من أجل استضافة، إيجاد وتثبيت الحِزَم.

البدء

فلنقم في البداية بإنشاء تطبيق بايثون بسيط وعام باستخدام إطار العمل المصغّر flask (إنشاء البنية) والذي يُمكننا لاحقًا تحزيمه.

التطبيق عبارة عن تطبيق ويب بسيط جدا، ﻷن الهدف من الدرس هو كيفية التحزيم وليس التطبيق في حد ذاته.

إنشاء بنية التطبيق

نهدف إلى إنشاء مثال يشابه معظم مشاريع العالم الحقيقي، ولهذا من الأفضل أن نتخيّل حالة تحتوي على وحدات.
بُنية المثال:

/MyApplication
|-- run.py
|-- config.py
|__ /app
     |-- __init__.py
     |-- /module_one
         |-- __init__.py
         |-- controllers.py
         |-- models.py                
     |__ /templates
         |-- module_one
             |-- hello.html
     |__ /static
     |__ ..
     |__ .

1. إنشاء المجلدات:

/MyApplication
|-- run.py
|-- config.py
|__ /app
     |-- __init__.py
     |-- /module_one
         |-- __init__.py
         |-- controllers.py
         |-- models.py                
     |__ /templates
         |-- module_one
             |-- hello.html
     |__ /static
     |__ ..
     |__ .

2. تعديل الملف run.py باستخدام برنامج nano:

nano ~/MyApplication/run.py

نضع المحتويات التّالية بداخله:

# Run a test server.
from app import app
app.run(debug=True)

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

3. تعديل الملف config.py باستخدام برنامج nano:

nano ~/MyApplication/config.py

نضع المحتويات التّالية بداخله:

DEBUG = True
THREADS_PER_PAGE = 4
CSRF_ENABLED     = True
CSRF_SESSION_KEY = "secret"

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

4. تعديل الملف app/init.py باستخدام برنامج nano:

nano ~/MyApplication/app/__init__.py

نضع المحتويات التّالية بداخله:

from flask import Flask, render_template

app = Flask(__name__)
app.config.from_object("config")

from app.module_one.controllers import module_one
app.register_blueprint(module_one)

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

5. تعديل الملف app/module_one/controllers.py باستخدام برنامج nano:

nano app/module_one/controllers.py

نضع المحتويات التّالية بداخله:

from flask import Blueprint, request, render_template

module_one = Blueprint("auth", __name__, url_prefix="/auth")

@module_one.route("/hello")
def hello():
    return render_template("module_one/hello.html")

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

6. تعديل الملف app/templates/module_one/hello.html باستخدام برنامج nano:

nano app/templates/module_one/hello.html

نضع المحتويات التّالية بداخله:

<DOCTYPE html>
<html lang="en">
<head>
    <title>{% block title %}My Site{% endblock %}</title>
    {% block css %}
    {% endblock %}
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 </head>
<body>
    Hello, world!
</body>
</html>

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

البدء بتوزيع وحزم التطبيق

بعد إنشاء بنية التطبيق المثالية لموقع ويب يستخدم flask، نستطيع المتابعة بالقيام بالخطوة الأولى في إعداد التوزيعة.

1. تبديل بنية المجلد

من أجل حَزْم تطبيقنا بشكل جيّد نحتاج للقيام ببعض الإضافات لبُنية مجلّدنا.

/MyApplication
|-- run.py
|__ /app
     |-- __init__.py
     |-- /module_one
         |-- __init__.py
         |-- controllers.py
         |-- models.py                
     |__ /templates
         |-- module_one
             |-- hello.html
     |__ /static
     |__ ..
     |__ .
|-- setup.py    # Distribution setup file
|-- README.txt  # Read-me file
|-- MANIFEST.in # Distribution manifest file
|-- CHANGES.txt # Changes log

فلنقم بتبديل بنية المجلد لإنشاء الملفات الضروريّة:

touch ~/MyApplication/setup.py
touch ~/MyApplication/README.py
touch ~/MyApplication/MANIFEST.py
touch ~/MyApplication/CHANGES.py
mv    ~/MyApplication/run.py ~/MyApplication/bin/run

2. إنشاء الملف setup.py

nano ~/MyApplication/setup.py

نضع المحتويات التّالية بداخله:

from distutils.core import setup

setup(
# Application name:
name="MyApplication",

# Version number (initial):
version="0.1.0",

# Application author details:
author="name surname",
author_email="name@addr.ess",

# Packages
packages=["app"],

# Include additional files into the package
include_package_data=True,

# Details
url="http://pypi.python.org/pypi/MyApplication_v010/",

#
# license="LICENSE.txt",
description="Useful towel-related stuff.",

# long_description=open("README.txt").read(),

# Dependent packages (distributions)
install_requires=[
    "flask",
],
)

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

3. إنشاء الملف MANIFEST.in

إن كنا نحتاج إلى شحن دلائل إضافية (ثابتة static أو قوالب templates) يجب علينا التصريح عنها في manifest لكي يتمّ حَزْمها، سنقوم بفعل هذا في MANIFEST.in.

nano ~/MyApplication/MANIFEST.in

نضع المحتويات التّالية بداخله:

recursive-include app/templates *
recursive-include app/static *

نقوم الآن بحفظه والخروج منه باستخدام CTRL+X ومن ثم تأكيد ذلك باستخدام Y.

هذا هو كل ما نحتاجه ، الآن حِزمة توزيعة بايثون جاهزة ليتمّ تثبيتها وشحنها.

4. ملفات إضافية

يجب دومًا أن نتذكّر أنّه من أجل الحصول على توزيعة كاملة يجب أن يكون الملف/الدليل محتويًا على الملفّات التالية ومربوطًا بها:

  • README.txt
  • MANIFEST.in
  • LICENSE.txt

التعامل مع التطبيق الجاهز للتوزيع

بعد أن انتهينا من إنشاء تطبيقنا ومن ثم أجرينا التبديلات الضرورية لبنية الملف لتحضيره لبناء توزيعة لا تحتوي على أيّة أخطاء، نستطيع الآن البدء بالمرور على عمليّات الحَزْم.

1. كيف نقوم بإنشاء ملف التوزيع

من أجل توليد نسخة ملف التوزيع، نقوم بتنفيذ الأمر التالي:

cd     ~/MyApplication
python setup.py sdist

سيذهب هذا الأمر إلى إعداداتنا، يطبع العمليات التي يتمّ تنفيذها ويُوَلِّد ملف أرشيف tar داخل الدليل الجديد diet، مشابهًا لما يلي:

# root@hostname:~/MyApplication# ls dist
# MyApplication-0.1.0.tar.gz

ملاحظة: بما أنّنا لم نقم بتأهيل جميع المجلدات الفرعية (مثل static) وتعاملنا مع ملفات إضافية (مثل README.txt)، فقد نحصل على بعض التحذيرات أثناء عمليّة الإنشاء.

2. كيفية تثبيت التطبيق

يستطيع الآخرون من الآن فصاعدًا تثبيت واستخدام التّطبيق باستخدام ملف setup.py الذي أنشأناه.

من أجل تثبيت التطبيق نقوم بتنفيذ الأوامر التالية:

python setup.py install

إن كان هذا التثبيت من أجل التطوير وأردنا تثبيت المُتطلّبات سنقوم بتنفيذ ما يلي:

python setup.py develop

3. كيفية مشاركة التطبيق

إن أردنا مشاركة الشيفرة على دليل حِزَم بايثون، نستطيع فعل ذلك عن طريق بدء الإجراء register كما يلي:

python setup.py register

نستطيع إكمال هذا الإجراء عبر اتّباع التّعليمات التي تظهر على الشّاشة.

وإن كنّا نملك تسجيل دخول مسجل registered login من أجل الرفع Upload فقط نستطيع استخدام الأمر التالي:

python setup.py sdist upload

4. كيفية إنشاء حزم من الإصدارات الجديدة للتطبيق

  1. نقوم بتحرير الملف setup.py عن طريق مُحرّر نصوص (مثل nano) وتعيين رقم الإصدار الجديد "version="0.1.1.
  2. نقوم بتحرير الملف CHANGES.txt لنعكس التغييرات.
  3. نقوم بإجراء التّعديلات الضّروريّة على الملفين LICENSE.txt و README.txt.
  4. رفع الشّيفرة بعد الخطوة السّابقة.

ترجمة -وبتصرّف- لـلمقال How To Package And Distribute Python Applications لصاحبه O.S. Tezer.

حقوق الصورة البارزة: Designed by Freepik.


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...