6. Modules
**********

Εάν βγείτε από τον interpreter της Python και μπείτε ξανά, οι ορισμοί
που έχετε κάνει (συναρτήσεις και μεταβλητές) χάνονται.  Επομένως, εάν
θέλετε να γράψετε ένα κάπως μεγαλύτερο πρόγραμμα, είναι προτιμότερο να
χρησιμοποιήσετε έναν επεξεργαστή κειμένου για να προετοιμάσετε την
εισαγωγή για τον interpreter και την εκτέλεση του με αυτό το αρχείο ως
input.  Αυτό είναι γνωστό ως δημιουργία *script*.  Καθώς το πρόγραμμα
σας μεγαλώνει, μπορεί να θέλετε να το χωρίσετε σε πολλά αρχεία για
ευκολότερη συντήρηση.  Μπορεί επίσης να θέλετε να χρησιμοποιήσετε μια
εύχρηστη συνάρτηση που έχετε γράψει σε πολλά προγράμματα χωρίς να
αντιγράψετε τον ορισμό της σε κάθε πρόγραμμα.

Για να το υποστηρίξει αυτό, η Python έχει έναν τρόπο να βάζει ορισμούς
σε ένα αρχείο και να τους χρησιμοποιεί σε ένα script ή σε ένα
διαδραστικό instance του interpreter.  Ένα τέτοιο αρχείο ονομάζεται
*module*∙ ορισμοί από μια ενότητα μπορούν να *εισαχθούν* σε άλλα
modules ή στο *κύριο* module (η συλλογή των μεταβλητών στις οποίες
έχετε πρόσβαση σε ένα script που εκτελείται στον ανώτερο επίπεδο και
σε λειτουργία αριθμομηχανής).

Ένα module είναι ένα αρχείο που περιέχει ορισμούς και δηλώσεις Python.
Το όνομα αρχείου είναι το όνομα του module με το επίθημα ".py".  Μέσε
σε ένα module, το όνομα του module (ως συμβολοσειρά) είναι διαθέσιμο
ως τιμή της global μεταβλητής "__name__".  Για παράδειγμα,
χρησιμοποιήστε το αγαπημένος σας πρόγραμμα επεξεργασίας κειμένου για
να δημιουργήσετε ένα αρχείο που ονομάζεται "fibo.py" στον τρέχοντα
κατάλογο με τα ακόλουθα περιεχόμενα:

   # Fibonacci numbers module

   def fib(n):    # write Fibonacci series up to n
       a, b = 0, 1
       while a < n:
           print(a, end=' ')
           a, b = b, a+b
       print()

   def fib2(n):   # return Fibonacci series up to n
       result = []
       a, b = 0, 1
       while a < n:
           result.append(a)
           a, b = b, a+b
       return result

Τώρα εισάγετε τον Python interpreter και εισάγετε αυτό το module με
την ακόλουθη εντολή:

   >>> import fibo

Αυτό δεν προσθέτει τα ονόματα των συναρτήσεων που ορίζονται στο "fibo"
απευθείας στον τρέχοντα *namespace* (βλ. Εμβέλεια και Πεδία Ονομάτων
στην Python για περισσότερες λεπτομέρειες): προσθέτει μόνο το όνομα
του module "fibo" εκεί. Χρησιμοποιώντας το όνομα του module μπορείτε
να αποκτήσετε πρόσβαση στις λειτουργίες:

   >>> fibo.fib(1000)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
   >>> fibo.fib2(100)
   [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
   >>> fibo.__name__
   'fibo'

Εάν σκοπεύετε να χρησιμοποιείτε συχνά μια συνάρτηση, μπορείτε να την
αντιστοιχίσετε σε ένα τοπικό όνομα:

   >>> fib = fibo.fib
   >>> fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377


6.1. Περισσότερα για τα Modules
===============================

Ένα module μπορεί να περιέχει εκτελέσιμες δηλώσεις καθώς και ορισμούς
συναρτήσεων. Αυτές οι δηλώσεις προορίζονται για την προετοιμασία του
module. Εκτελούνται μόνο την *πρώτη* φορά που εμφανίζεται το όνομα του
module σε μια δήλωση εισαγωγής. [1] (Εκτελούνται επίσης εάν το αρχείο
εκτελείται ως script.)

Κάθε module έχει τον δικό της ιδιωτικό namespace, ο οποίος
χρησιμοποιείται ως global namespace από όλες τις συναρτήσεις που
ορίζονται στο module. Έτσι, ο συντάκτης μιας ενότητας μπορεί να
χρησιμοποιήσει global μεταβλητές στο module χωρίς να ανησυχεί για
τυχαία conflicts με τις global μεταβλητές του χρήστη. Από την άλλη
πλευρά, εάν ξέρετε τι κάνετε, μπορείτε να αγγίξετε τις global
μεταβλητές ενός module με το ίδιο notation που χρησιμοποιείται για να
αναφέρεται στις συναρτήσεις, "modname.itemname".

Τα modules μπορούν να εισάγουν άλλα modules.  Είναι σύνηθες, αλλά δεν
απαιτείται να τοποθετούνται όλες οι δηλώσεις "import" στην αρχή μιας
ενότητα (ή σεναρίου, για αυτό το θέμα).  Τα ονόματα των modules που
εισάγονται, εάν τοποθετούνται στο ανώτερο επίπεδο του ένα module
(εκτός οποιωνδήποτε συναρτήσεων ή κλάσεων), προστίθενται στον global
namespace του module.

Υπάρχει μια παραλλαγή της δήλωσης "import" που εισάγει ονόματα από ένα
module απευθείας στον χώρο στα importing module's namespace.  Για
παράδειγμα:

   >>> from fibo import fib, fib2
   >>> fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Αυτό δεν εισάγει το όνομα ενός module από το οποίο λαμβάνονται οι
εισαγωγές στο τοπικό namespace (αρά στο παράδειγμα, το "fibo" δεν
ορίζεται).

Υπάρχει ακόμη και μια παραλλαγή για την εισαγωγή όλων των ονομάτων που
ορίζει μια ενότητα:

   >>> from fibo import *
   >>> fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Αυτό εισάγει όλα τα ονόματα εκτός από αυτά που ξεκινούν με κάτω παύλα
("_"). Στις περισσότερες περιπτώσεις, οι προγραμματιστές Python δεν
χρησιμοποιούν αυτήν την δυνατότητα , καθώς εισάγει ένα άγνωστο σύνολο
ονομάτων στον interpreter, κρύβοντας πιθανώς κάποια πράγματα που έχετε
ήδη ορίσει.

Λάβετε υπόψη ότι γενικά η πρακτική της εισαγωγής "*" από ένα module ή
ένα πακέτο αποδοκιμάζεται, καθώς προκαλεί συχνά κακώς αναγνώσιμο
κώδικα. Ωστόσο, είναι εντάξει να τον χρησιμοποιήσετε για να
αποθηκεύσετε την πληκτρολόγηση σε διαδραστικές περιόδους σύνδεσης.

Εάν το όνομα του module ακολουθείται από "as", τότε το όνομα που
ακολουθεί "as" συνδέεται απευθείας με το εισαγόμενο module.

   >>> import fibo as fib
   >>> fib.fib(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Αυτό ουσιαστικά εισάγει το module με τον ίδιο τρόπο που θα κάνει το
"import fibo" , με τη μόνη διαφορά ότι είναι διαθέσιμο ως "fib".

Μπορεί επίσης να χρησιμοποιηθεί όταν χρησιμοποιείτε "from" με παρόμοια
εφέ:

   >>> from fibo import fib as fibonacci
   >>> fibonacci(500)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Σημείωση:

  Για λόγους αποτελεσματικότητας, κάθε module εισάγεται μόνο μία φορά
  ανά περίοδο λειτουργίες του interpreter.  Επομένως, εάν αλλάξετε τα
  modules σας, πρέπει να επανεκκινήσετε τον διερμηνέα -- ή, εάν είναι
  μόνο ένα module που θέλετε να δοκιμάσετε διαδραστικά, χρησιμοποιήστε
  το "importlib.reload()", π.χ. "import importlib;
  importlib.reload(modulename)".


6.1.1. Εκτέλεση modules ως scripts
----------------------------------

Όταν εκτελείτε ένα Python module με:

   python fibo.py <arguments>

ο κώδικας στο module θα εκτελεστεί, ακριβώς σαν να τον εισαγάγετε,
αλλά με το "name" να έχει οριστεί σε ""__main__"".  Αυτό σημαίνει ότι
προσθέτοντας αυτόν τον κώδικα στο τέλος του module σας:

   if __name__ == "__main__":
       import sys
       fib(int(sys.argv[1]))

μπορείτε να κάνετε το αρχείο χρησιμοποιήσιμο ως script καθώς και ως
module που μπορεί να εισαχθεί, επειδή ο κώδικας που αναλύει την γραμμή
εντολών εκτελείται μόνο εάν το module εκτελείται ως το "main" αρχείο:

   $ python fibo.py 50
   0 1 1 2 3 5 8 13 21 34

Εάν το module έχει εισαχθεί, ο κώδικας δεν εκτελείται:

   >>> import fibo
   >>>

Αυτό χρησιμοποιείται συχνά είτε για την παροχή ενός βολικού user
interface σε ένα module, είτε για σκοπούς δοκιμής (η εκτέλεση του
module ως script εκτελεί μια δοκιμαστική σουίτα).


6.1.2. Το Search Path του Module
--------------------------------

Όταν εισάγετε ένα module με το όνομα "spam", ο interpreter αναζητά
πρώτα ένα ενσωματωμένο module με αυτό το όνομα. Αυτά τα ονόματα των
module παρατίθενται στο "sys.builtin_module_names". Εάν δεν βρεθεί,
τότε αναζητά ένα αρχείο με το όνομα "spam.py" σε μια λίστα καταλόγων
που δίνονται από τη μεταβλητή "sys.path".  Το "sys.path"
αρχικοποιείται από αυτές τις θέσεις:

* Ο κατάλογος που περιέχει το input script (ή τον τρέχοντα κατάλογο
  όταν δεν έχει καθοριστεί αρχείο).

* "PYTHONPATH" (μια λίστα ονομάτων καταλόγου, με την ίδια σύνταξη με
  τη μεταβλητή του shell "PATH").

* Η προεπιλογή που εξαρτάται από την εγκατάσταση (κατά σύμβαση,
  συμπεριλαμβανομένου ενός καταλόγου "site-packages", που χειρίζεται
  το module "site".

Περισσότερες λεπτομέρειες βρίσκονται στο The initialization of the
sys.path module search path.

Σημείωση:

  Στα συστήματα αρχείων που υποστηρίζουν symlinks, ο κατάλογο που
  περιέχει το input script υπολογίζεται αφού ακολουθηθεί το symlink.
  Με άλλα λόγια, ο κατάλογος που περιέχει το symlink **δεν**
  προστίθεται στη διαδρομή αναζήτησης του module.

Μετά την προετοιμασία, τα προγράμματα Python μπορούν να τροποποιήσουν
το "sys.path".  Ο κατάλογος που περιέχει το script που εκτελείται
τοποθετείται στην αρχή της διαδρομής αναζήτησης , μπροστά από την
τυπική διαδρομή της βιβλιοθήκης. Αυτό σημαίνει ότι τα scripts σε αυτόν
τον κατάλογο θα είναι φορτωμένα αντί για τα modules με το ίδιο όνομα
στον κατάλογο μιας βιβλιοθήκης. Αυτό είναι ένα σφάλμα, εκτός εάν
προορίζεται η αντικατάσταση.  Βλ. την ενότητα Standard Modules για
περισσότερες πληροφορίες.


6.1.3. "Compiled" Python αρχεία
-------------------------------

Για να επιταχύνει τη φόρτωση modules, η Python κάνει cache την
compiled έκδοση κάθε module στον κατάλογο "__pycache__" κάτω από το
όνομα "module.*version*.pyc", όπου η έκδοση κωδικοποιεί τη μορφή του
compiled αρχείου∙ γενικά περιέχει τον αριθμό έκδοσης της Python.  Για
παράδειγμα, στην έκδοση CPython 3.3 η compiled έκδοση του spam.py θα
αποθηκευτεί ως "__pycache__/spam.cpython-33.pyc".  Αυτή η σύμβαση
ονομασίας, επιτρέπει σε compiled modules από διαφορετικές εκδόσεις και
διαφορετικές εκδόσεις της Python να συνυπάρχουν.

Η Python ελέγχει την ημερομηνία τροποποίησης του πηγαίου έναντι της
compiled έκδοσης για να δει εάν είναι ξεπερασμένη και χρειάζεται να
γίνει compile ξανά.  Αυτή είναι μια εντελώς αυτόματη διαδικασία.
Επίσης, τα compiled modules είναι ανεξάρτητες από πλατφόρμα, επομένως
η ίδια βιβλιοθήκη μπορεί να κοινοποιηθεί ανάμεσα σε συστήματα με
διαφορετικές αρχιτεκτονικές.

Η Python δεν ελέγχει την cache σε δύο περιπτώσεις.  Πρώτον, πάντα
κάνει compile ξανά και δεν αποθηκεύει το αποτέλεσμα για το module που
φορτώνεται απευθείας από τη γραμμή εντολών.  Δεύτερον, δεν ελέγχει τη
μνήμη cache εάν δεν υπάρχει το source module.  Για να υποστηρίξετε μια
διανομή χωρίς πηγαίο (compiled μόνο), το compiled module πρέπει να
βρίσκεται στον source κατάλογο και δεν πρέπει να υπάρχει source
module.

Μερικές συμβουλές για ειδικούς:

* Μπορείτε να χρησιμοποιήσετε τους switches "-O" ή "-OO" στην εντολή
  Python για να μειώσετε το μέγεθος ενός compiled module.  Το "-O"
  switch αφαιρεί τις assert statements, το "-OO" switch αφαιρεί τόσο
  τα assert statements όσο και τις __doc__ συμβολοσειρές . Εφόσον
  ορισμένα προγράμματα μπορεί να βασίζονται στην ύπαρξη αυτών των
  διαθέσιμων, θα πρέπει να χρησιμοποιήσετε αυτήν την επιλογή μόνο εάν
  γνωρίζετε τι κάνετε.  "Optimized" modules έχουν ένα "opt-" tag και
  είναι συνήθως μικρότερες.  Οι μελλοντικές εκδόσεις μπορεί να
  αλλάξουν τα αποτελέσματα της βελτιστοποίησης.

* Ένα πρόγραμμα δεν εκτελείται πιο γρήγορα όταν διαβάζεται από ένα
  αρχείο ".pyc" από ό,τι όταν διαβάζεται από ένα αρχείο ".py``∙ το
  μόνο πράγμα που είναι πιο γρήγορο από τα αρχεία ``.pyc" είναι η
  ταχύτητα με την οποία φορτώνονται.

* Το module "compileall" μπορεί να δημιουργήσει αρχεία .pyc για όλα τα
  modules σε ένα κατάλογο.

* Υπάρχουν περισσότερες λεπτομέρειες σχετικά με αυτή τη διαδικασία,
  συμπεριλαμβανομένου ενός διαγράμματος ροής των αποφάσεων, στο **PEP
  3147**.


6.2. Standard Modules
=====================

Η Python συνοδεύεται από μια βιβλιοθήκη standard modules, η οποία
περιγράφεται σε ένα ξεχωριστό έγγραφο, την Αναφορά Βιβλιοθήκης Python
("Library Reference" hereafter).  Ορισμένα modules είναι ενσωματωμένα
στον interpreter∙ αυτές παρέχουν πρόσβαση σε λειτουργίες που δεν
αποτελούν μέρος του πυρήνα της γλώσσας, αλλά εντούτοις είναι
ενσωματωμένα, είτε για αποτελεσματικότητα είτε για την παροχή
πρόσβασης σε πρωτόγονα στοιχεία του λειτουργικού συστήματος όπως οι
κλήσεις συστήματος.  Το σύνολο τέτοιων modules είναι μια επιλογή
διαμόρφωσης που εξαρτάται επίσης από την υποκείμενη πλατφόρμα.  Για
παράδειγμα, το module "winreg" παρέχεται μόνο σε συστήματα Windows.
Ένα συγκεκριμένο module που αξίζει κάποια προσοχή είναι το "sys", το
οποίο είναι ενσωματωμένο στον interpreter της Python.  Οι μεταβλητές
"sys.ps1" και "sys.ps2" ορίζουν τις συμβολοσειρές που χρησιμοποιούνται
ως κύρια και δευτερεύοντα prompts:

   >>> import sys
   >>> sys.ps1
   '>>> '
   >>> sys.ps2
   '... '
   >>> sys.ps1 = 'C> '
   C> print('Yuck!')
   Yuck!
   C>

Αυτές οι δύο μεταβλητές ορίζονται μόνο εάν ο interpreter βρίσκεται σε
διαδραστική λειτουργία.

Η μεταβλητή "sys.path" είναι μια λίστα συμβολοσειρών που καθορίζει τη
διαδρομή αναζήτησης του διερμηνέα για modules. Αρχικοποιείται σε μια
προεπιλεγμένη διαδρομή που λαμβάνεται από τη μεταβλητή περιβάλλοντος
"PYTHONPATH", ή από μια ενσωματωμένη προεπιλογή εάν το "PYTHONPATH"
δεν έχει οριστεί.  Μπορείτε να το τροποποιήσετε χρησιμοποιώντας
τυπικές λειτουργίες λίστας:

   >>> import sys
   >>> sys.path.append('/ufs/guido/lib/python')


6.3. Η συνάρτηση "dir()"
========================

Η ενσωματωμένη συνάρτηση "dir()" χρησιμοποιείται για να ανακαλύψει
ποια ονόματα ορίζει ένα module.  Επιστρέφει μια ταξινομημένη λίστα
συμβολοσειρών:

   >>> import fibo, sys
   >>> dir(fibo)
   ['__name__', 'fib', 'fib2']
   >>> dir(sys)  
   ['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
    '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
    '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
    '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
    '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
    'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
    'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
    'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
    'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
    'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
    'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
    'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
    'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
    'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
    'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
    'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
    'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
    'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
    'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
    'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
    'warnoptions']

Χωρίς ορίσματα, η "dir()" παραθέτει τα ονόματα που έχετε ορίσει αυτήν
τη στιγμή:

   >>> a = [1, 2, 3, 4, 5]
   >>> import fibo
   >>> fib = fibo.fib
   >>> dir()
   ['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

Λάβετε υπόψη ότι παραθέτει όλους τους τύπους ονομάτων: μεταβλητές,
modules, συναρτήσεις, κ.λπ.

Η "dir()" δεν παραθέτει τα ονόματα των ενσωματωμένων συναρτήσεων και
μεταβλητών.  Εάν θέλετε μια λίστα από αυτές, ορίζονται στην τυπική
ενότητα "builtins":

   >>> import builtins
   >>> dir(builtins)  
   ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
    'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
    'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
    'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
    'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
    'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
    'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
    'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
    'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
    'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
    'NotImplementedError', 'OSError', 'OverflowError',
    'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
    'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
    'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
    'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
    'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
    'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
    'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
    '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
    'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
    'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
    'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
    'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
    'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
    'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
    'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
    'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
    'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
    'zip']


6.4. Πακέτα
===========

Τα πακέτα είναι ένας τρόπος δόμησης του namespace του module
χρησιμοποιώντας "dotted module names".  Για παράδειγμα, το όνομα του
module "A.B" υποδηλώνει ένα submodule με όνομα "B" σε ένα πακέτο με
όνομα "A".  Ακριβώς όπως η χρήση των modules σώζει τους δημιουργούς
διαφορετικών modules να ανησυχούν ο ένας για τα καθολικά ονόματα
μεταβλητών του άλλου, η χρήση dotted module ονομάτων σώζει τους
δημιουργούς των multi-module πακέτων όπως το NumbPY ή το Pillow από το
να χρειάζεται να ανησυχούν ο ένας για τα module ονόματα του άλλου.

Ας υποθέσουμε ότι θέλετε να σχεδιάσετε μια συλλογή από module (ένα
"πακέτο") για τον ομοιόμορφο χειρισμό αρχείων ήχου και δεδομένων ήχου.
Υπάρχουν πολλές διαφορετικές μορφές αρχείων ήχου (που συνήθως
αναγνωρίζονται από την επέκτασή τους, για παράδειγμα: ".wav", ".aiff",
".au"), επομένως μπορεί να χρειαστεί να δημιουργήσετε και να
διατηρήσετε μια αυξανόμενη συλλογή λειτουργιών για τη μετατροπή μεταξύ
των διαφόρων μορφών αρχείων. Υπάρχουν επίσης πολλές διαφορετικές
λειτουργίες που μπορεί να θέλετε να εκτελέσετε σε δεδομένα ήχου (όπως
μίξη, προσθήκη ηχούς, εφαρμογή μιας λειτουργίας ισοσταθμιστή,
δημιουργία τεχνητού στερεοφωνικού εφέ), επομένως επιπλέον θα γράφετε
μια ατελείωτη ροή από modules για να εκτελέσετε αυτές τις λειτουργίες.
Ακολουθεί μια πιθανή δομή για το πακέτο σας (που εκφράζεται ως
ιεραρχικό σύστημα αρχείων):

   sound/                          Top-level package
         __init__.py               Initialize the sound package
         formats/                  Subpackage for file format conversions
                 __init__.py
                 wavread.py
                 wavwrite.py
                 aiffread.py
                 aiffwrite.py
                 auread.py
                 auwrite.py
                 ...
         effects/                  Subpackage for sound effects
                 __init__.py
                 echo.py
                 surround.py
                 reverse.py
                 ...
         filters/                  Subpackage for filters
                 __init__.py
                 equalizer.py
                 vocoder.py
                 karaoke.py
                 ...

Κατά την εισαγωγή του πακέτου, η Python πραγματοποιεί αναζήτηση στους
καταλόγους στο "sys.path" αναζητώντας τον υποκατάλογο του πακέτου.

Τα "__init__.py" αρχεία απαιτούνται για να κάνει την Python να
αντιμετωπίζει του καταλόγου που περιέχουν το αρχείο ως πακέτα (εκτός
εάν χρησιμοποιεί ένα *namespace package*, ένα σχετικά προηγμένο
χαρακτηριστικό). Αυτό αποτρέπει τους καταλόγους με κοινό όνομα, όπως
π.χ. ως "string", από την ακούσια απόκρυψη έγκυρων modules που
εμφανίζονται αργότερα στο path αναζήτησης του module. Στην απλούστερη
περίπτωση, το "__init__.py" μπορεί απλώς να είναι κενό αρχείο, αλλά
μπορεί επίσης να εκτελέσει initialization κώδικα για το πακέτο ή να
ορίσει την μεταβλητή "__all__", που περιγράφεται αργότερα.

Οι χρήστες του πακέτου μπορούν να εισάγουν μεμονωμένα module από το
πακέτο, για παράδειγμα:

   import sound.effects.echo

Αυτό φορτώνει το submodule "sound.effects.echo".  Πρέπει να αναφέρεται
με το πλήρες όνομά του.

   sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

Ένα εναλλακτικός τρόπος για την εισαγωγή του submodule είναι:

   from sound.effects import echo

Αυτό φορτώνει επίσης το submodule "echo", και την καθιστά διαθέσιμη
χωρίς το πρόθεμα πακέτου, ώστε να μπορεί να χρησιμοποιηθεί ως εξής:

   echo.echofilter(input, output, delay=0.7, atten=4)

Μια άλλη παραλλαγή είναι η απευθείας εισαγωγή της επιθυμητής
συνάρτησης ή μεταβλητής:

   from sound.effects.echo import echofilter

Και πάλι, αυτό φορτώνει το submodule "echo", αλλά αυτό κάνει τη
συνάρτηση της "echofilter()" άμεσα διαθέσιμη:

   echofilter(input, output, delay=0.7, atten=4)

Λάβετε υπόψη ότι όταν χρησιμοποιείτε "from package import item", το
στοιχείο μπορεί να είναι είτε submodule (ή υποπακέτο) του πακέτου ή
κάποιο άλλο όνομα που ορίζεται στο πακέτο, όπως μια συνάρτηση, κλάση ή
μεταβλητή. Η "import" δήλωση ελέγχει πρώτα εάν το στοιχείο έχει
οριστεί στο πακέτο, εάν όχι, υποθέτει ότι είναι ένα module και
επιχειρεί να το φορτώσει , αν δεν το βρει δημιουργεί η εξαίρεση
"ImportError".

Αντίθετα, όταν χρησιμοποιείται σύνταξη όπως "import
item.subitem.subsubitem", κάθε στοιχείο εκτός από αυτό το τελευταίο
πρέπει να είναι πακέτο∙ το τελευταίο στοιχείο μπορεί να είναι ένα
module ή ένα πακέτο αλλά δεν μπορεί να είναι μια κλάση ή συνάρτηση ή
μεταβλητή που ορίζεται από προηγούμενο στοιχείο.


6.4.1. Εισάγοντας * από ένα Πακέτο
----------------------------------

Τώρα τι συμβαίνει όταν ο χρήστης γράφει "from sound.effects import *";
Ιδανικά, θα ήλπιζε κανείς ότι αυτό θα βγει με κάποιο τρόπο στο σύστημα
αρχείων, θα βρει κάποια submodules που υπάρχουν το πακέτο, και θα τα
εισάγει όλα σε αυτό.  Αυτό θα μπορούσε να πάρει πολύ χρόνο και η
εισαγωγή submodules μπορεί να έχει ανεπιθύμητες παρενέργειες που θα
έπρεπε να συμβούν όταν το submodule εισάγεται ρητά.

Η μόνη λύση είναι να παρέχει ο συντάκτης του πακέτου ένα ρητό
ευρετήριο του πακέτου.  Η δήλωση "import" χρησιμοποιεί την ακόλουθη
σύμβαση: εάν ο κώδικας "__init__.py" του πακέτου ορίζει μια λίστα με
το όνομα "__all__", θεωρείται ότι είναι η λίστα με τα ονόματα των
modules που θα πρέπει να εισαχθούν όταν συναντήσετε "from package
import *".  Είναι στην διακριτή ευχέρεια του συντάκτη του πακέτου να
διατηρεί αυτή τη λίστα ενημερωμένη, όταν κυκλοφορήσει μια νέα έκδοση
του πακέτου.  Οι συντάκτες του πακέτου ενδέχεται επίσης να αποφασίσουν
να μην το υποστηρίξουν, εάν δεν βλέπουν ότι χρησιμοποιείται η εισαγωγή
του * από το πακέτο τους.  Για παράδειγμα το αρχείο
"sound/effects/__init__.py" θα μπορούσε να περιέχει τον ακόλουθο
κώδικα:

   __all__ = ["echo", "surround", "reverse"]

Αυτό θα σήμαινε ότι "from sound.effects import *" θα εισαγάγει τα τρία
submodules με το όνομα του πακέτου "sound.effects".

Λάβετε υπόψη ότι τα submodules ενδέχεται να σκιάζονται από τοπικά
καθορισμένα ονόματα. Για παράδειγμα, εάν προσθέσατε μια "reverse"
συνάρτηση στο αρχείο "sound/effects/__init__.py", το "from
sound.effects import *" θα εισαγάγει μόνο τα δύο submodules "echo" και
"surround", αλλά *όχι* το submodule "reverse", επειδή επισκιάζεται από
την τοπικά καθορισμένη συνάρτηση "reverse":

   __all__ = [
       "echo",      # refers to the 'echo.py' file
       "surround",  # refers to the 'surround.py' file
       "reverse",   # !!! refers to the 'reverse' function now !!!
   ]

   def reverse(msg: str):  # <-- this name shadows the 'reverse.py' submodule
       return msg[::-1]    #     in the case of a 'from sound.effects import *'

Εάν δεν έχει οριστεί το "__all__", η δήλωση "from sound.effects import
*" *δεν* εισάγει όλα τα submodules από το πακέτο "sound.effects" στο
τρέχων namespace∙ διασφαλίζει μόνο ότι το πακέτο "sound.effects" έχει
εισαχθεί (ενδεχομένως να εκτελείται οποιοσδήποτε κωδικός προετοιμασίας
στο στο "__init__.py") και στη συνέχεια εισάγει οποιαδήποτε ονόματα
ορίζονται στο πακέτο. Αυτό περιλαμβάνει τυχόν ονόματα που ορίζονται
(και submodules που έχουν φορτωθεί ρητά) από το "__init__.py".
Περιλαμβάνει επίσης τυχόν submodules του πακέτου που φορτώθηκαν ρητά
από προηγούμενες δηλώσεις "import".  Σκεφτείτε αυτόν τον κώδικα:

   import sound.effects.echo
   import sound.effects.surround
   from sound.effects import *

Σε αυτό το παράδειγμα, τα modules "echo" και "surround" εισάγονται στο
τρέχον namespace επειδή ορίζονται στο πακέτο "sound.effects`όταν η
δήλωση ``from...import`" εκτελείται.  (Αυτό λειτουργεί επίσης όταν
ορίζεται το "__all__").

Αν και ορισμένα modules έχουν σχεδιαστεί για να εξάγουν μόνο ονόματα
που ακολουθούν ορισμένα μοτίβα όταν χρησιμοποιείτε το "import *",
εξακολουθεί να θεωρείται κακή πρακτική στον κώδικα παραγωγής.

Θυμηθείτε, δεν υπάρχει τίποτα κακό με τη χρήση του "from package
import specific_submodule"!  Στην πραγματικότητα, αυτή είναι η
προτεινόμενη σημείωση, εκτός εάν το module εισαγωγής χρειάζεται να
χρησιμοποιήσει submodules με το ίδιο όνομα από διαφορετικά πακέτα.


6.4.2. Intra-package αναφορές
-----------------------------

Όταν τα πακέτα είναι δομημένα σε υποπακέτα (όπως με το πακέτο "sound"
στο παράδειγμα), μπορείτε να χρησιμοποιήσετε απόλυτες εισαγωγές για να
αναφερθείτε σε submodules αδερφών πακέτων.  Για παράδειγμα, εάν το
module "sound.filters.vocoder" πρέπει να χρησιμοποιήσει το module
"echo" στο πακέτο "sound.effects" , μπορεί να χρησιμοποιήσει το "from
sound.effects import echo".

Μπορείτε επίσης να γράψετε σχετικές εισαγωγές, με τη φόρμα "from
module import name" της δήλωσης εισαγωγής.  Αυτές οι εισαγωγές
χρησιμοποιούν leading dots για να υποδείξουν τα τρέχοντα και γονικά
πακέτα που εμπλέκονται στη σχετική εισαγωγή.  Από το "surround" module
για παράδειγμα, μπορεί να χρησιμοποιήσετε:

   from . import echo
   from .. import formats
   from ..filters import equalizer

Λάβετε υπόψη ότι οι σχετικές εισαγωγές βασίζονται στο όνομα του
τρέχοντος module.  Επειδή το όνομα του κύριου module είναι πάντα
""__main__"", τα modules που προορίζονται για χρήση ως κύριο module
μιας εφαρμογής Python πρέπει πάντα να χρησιμοποιούν απόλυτες
εισαγωγές.


6.4.3. Πακέτα σε Πολλαπλούς Καταλόγους
--------------------------------------

Packages support one more special attribute, "__path__".  This is
initialized to be a list containing the name of the directory holding
the package's "__init__.py" before the code in that file is executed.
This variable can be modified; doing so affects future searches for
modules and subpackages contained in the package.

Ενώ αυτή η δυνατότητα δεν χρειάζεται συχνά, μπορεί να χρησιμοποιηθεί
για την επέκταση του συνόλου των modules που βρίσκονται σε ένα πακέτο.

-[ Υποσημειώσεις ]-

[1] Στην πραγματικότητα, οι ορισμοί συναρτήσεων είναι επίσης
    'statements' που 'εκτελούνται'∙ η εκτέλεση ενός ορισμού συνάρτησης
    σε επίπεδο module προσθέτει το όνομα της συνάρτησης στον καθολικό
    namespace του module.
