Python στα Windows FAQ
**********************


Πως μπορώ να εκτελέσω ένα πρόγραμμα Python στα Windows;
=======================================================

Αυτό δεν είναι απαραίτητα μια απλή ερώτηση. Εάν είστε ήδη
εξοικειωμένοι με την εκτέλεση προγραμμάτων από τη γραμμή εντολών των
Windows τότε όλα θα φαίνονται προφανή' διαφορετικά, μπορεί να
χρειαστεί λίγη περισσότερη καθοδήγηση.

Εκτός και αν χρησιμοποιείτε κάποιο είδος ενσωματωμένου περιβάλλοντος
ανάπτυξης, θα καταλήξετε πληκτρολογώντας εντολές των Windows σε αυτό
που αναφέρεται ως "Command prompt window".  Συνήθως μπορείτε να
δημιουργήσετε ένα τέτοιο παράθυρο από τη γραμμή αναζήτησης σας
κάνοντας αναζήτηση για "cmd".  Θα πρέπει να μπορείτε να αναγνωρίσετε
πότε έχετε ξεκινήσει ένα τέτοιο παράθυρο επειδή θα δείτε ένα "command
prompt" των Windows, η οποία συνήθως μοιάζει με αυτό:

   C:\>

Το γράμμα μπορεί να είναι διαφορετικό, και μπορεί να υπάρχουνε άλλα
πράγματα μετά από αυτό, έτσι μπορείτε να δείτε εξίσου εύκολα κάτι σαν:

   D:\YourName\Projects\Python>

ανάλογα με το πως έχει ρυθμιστεί ο υπολογιστής σας και τι άλλο έχετε
κάνει με αυτόν.  Μόλις ξεκινήσετε ένα τέτοιο παράθυρο, είστε σε καλό
δρόμο για την εκτέλεση προγραμμάτων Python.

Πρέπει να συνειδητοποιήσετε ότι τα Python σενάρια σας πρέπει να
επεξεργαστούν από άλλο πρόγραμμα που ονομάζεται Python *interpreter*.
Ο interpreter διαβάζει το σενάριο σας, το κάνει compile σε bytecodes
και στη συνέχεια εκτελεί τα bytecodes για να τρέξει το πρόγραμμά σας.
Λοιπόν, πως ρυθμίζετε τον interpreter για να χειριστεί την Python σας;

Πρώτα από όλα, πρέπει να σιγουρευτείτε ότι το παράθυρο εντολών σας
αναγνωρίζει την λέξη "py" ως οδηγία για την έναρξη του interpreter.
Εάν έχετε ανοίξει ένα παράθυρο εντολών, θα πρέπει να δοκιμάσετε να
εισαγάγετε την εντολή "py" και να πατήσετε return:

   C:\Users\YourName> py

Στη συνέχεια, θα πρέπει να δείτε κάτι σαν:

   Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32
   Type "help", "copyright", "credits" or "license" for more information.
   >>>

Έχετε ξεκινήσει τον interpreter σε "interactive mode". Αυτό σημαίνει
ότι μπορείτε να εισάγετε δηλώσεις ή εκφράσεις Python διαδραστικά και
να τις εκτελείτε ή να τις αξιολογείτε ενώ περιμένετε.  Αυτό είναι ένα
από τα ισχυρότερα χαρακτηριστικά της Python.  Ελέγξτε το εισάγοντας
μερικές εκφράσεις της επιλογή σας και βλέποντας τα αποτελέσματα:

   >>> print("Hello")
   Hello
   >>> "Hello" * 3
   'HelloHelloHello'

Πολλοί άνθρωποι χρησιμοποιούν τη διαδραστική λειτουργία ως μια βολική
αλλά εξαιρετικά προγραμματιζόμενη αριθμομηχανή.  Όταν θέλετε να
τερματίσετε τη διαδραστική συνεδρία Python, καλέστε τη συνάρτηση
"exit()" ή κρατήστε πατημένο το πλήκτρο "Ctrl" ενώ εισάγετε ένα "Z",
και μετά πατήστε το πλήκτρο ""Enter"" για να επιστρέψετε στο command
prompt των Windows.

Μπορεί επίσης να διαπιστώσετε ότι έχετε μια καταχώρηση στο Start-menu
όπως Start ‣ Programs ‣ Python 3.x ‣ Python (command line) που έχει ως
αποτέλεσμα να βλέπετε το ">>>" σε ένα νέο παράθυρο, το παράθυρο θα
εξαφανιστεί αφού καλέσετε τη συνάρτηση "exit()" ή εισαγάγετε τον
χαρακτήρα "Ctrl-Z"' τα Windows εκτελούν μία μόνο εντολή "python" στο
παράθυρο και την κλείνουν όταν τερματίζετε τον interpreter.

Τώρα που γνωρίζουμε ότι η εντολή "py" αναγνωρίζεται, μπορείτε να της
δώσετε το σενάριο Python σας. Θα πρέπει να δώσετε είτε μια απόλυτη
είτε μια σχετική διαδρομή προς στο σενάριο Python. Ας υποθέσουμε ότι
το σενάριο Python σας βρίσκεται στην επιφάνεια εργασίας σας και
ονομάζεται "hello.py", και η γραμμή εντολών σας ανοίγει όμορφα στον
αρχικό σας κατάλογο, ώστε να βλέπετε κάτι παρόμοιο με:

   C:\Users\YourName>

Λοιπόν τώρα θα ζητήσετε από την εντολή "py" να δώσει το σενάριο σας
στην Python πληκτρολογώντας "py" ακολουθούμενη από τη διαδρομή του
σεναρίου σας:

   C:\Users\YourName> py Desktop\hello.py
   hello


Πως κάνω τα Python scripts εκτελέσιμα;
======================================

Στα Windows, το τυπικό πρόγραμμα εγκατάστασης Python ήδη συσχετίζει
την επέκταση .py με έναν τύπο αρχείου μια ανοιχτή εντολή που εκτελεί
τον διερμηνέα ("D:\Program Files\Python\python.exe "%1" %*").  Αυτό
είναι αρκετό για να κάνετε τα scripts εκτελέσιμα από τη γραμμή εντολών
ως 'foo.py'.  Εάν προτιμάτε να μπορείτε να εκτελέσετε το σενάριο
πληκτρολογώντας απλά 'foo' χωρίς επέκταση, πρέπει να προσθέσετε .py
στη μεταβλητή περιβάλλοντος PATHTEXT.


Γιατί μερικές φορές η Python αργεί τόσο πολύ να ξεκινήσει;
==========================================================

Συνήθως η Python ξεκινά πολύ γρήγορα στα Windows, αλλά περιστασιακά
υπάρχουν αναφορές σφαλμάτων ότι η Python αρχίζει ξαφνικά να παίρνει
πολύ χρόνο για να ξεκινήσει.  Αυτό γίνεται ακόμα πιο αινιγματικό,
επειδή η Python θα λειτουργεί καλά σε άλλα συστήματα Windows που
φαίνεται να έχουν διαμορφωθεί με τον ίδιο τρόπο.

Το πρόβλημα μπορεί να οφείλεται σε εσφαλμένη διαμόρφωση του λογισμικού
ελέγχου ιών στο προβληματικό μηχάνημα.  Ορισμένοι σαρωτές ιών είναι
γνωστό ότι εισάγουν επιβάρυνση εκκίνησης δύο τάξεων μεγέθους όταν ο
σαρωτής έχει ρυθμιστεί να παρακολουθεί όλες τις αναγνώσεις από το
σύστημα αρχείων.  Δοκιμάστε να ελέγξετε τη διαμόρφωση του λογισμικού
ιών στα συστήματά σας για να βεβαιωθείτε ότι έχουν όντως διαμορφωθεί
πανομοιότυπα.  Το McAfee, όταν έχει ρυθμιστεί να σαρώνει όλη τη
δραστηριότητα ανάγνωσης του συστήματος αρχείων , είναι ένας
συγκεκριμένος φταίχτης.


Πώς μπορώ να δημιουργήσω ένα εκτελέσιμο από ένα σενάριο Python;
===============================================================

Βλ. Πως μπορώ να δημιουργήσω ένα stand-alone binary από ένα Python
script; για μια λίστα εργαλείων που μπορούν να χρησιμοποιηθούν για τη
δημιουργία εκτελέσιμων αρχείων.


Είναι ένα αρχείο "*.pyd" ίδιο με ένα αρχείο DLL;
================================================

Ναι, τα αρχεία .pyd είναι dll, αλλά υπάρχουν μερικές διαφορές.  Εάν
έχετε ένα DLL με το όνομα "foo.pyd", τότε πρέπει να έχει μια συνάρτηση
"PyInit_foo()".  Στη συνέχεια μπορείτε να γράψετε Python "import foo",
και η Python θα αναζητήσει το foo.pyd (καθώς και το foo.py, foo.pyc)
και να το βρει, θα προσπαθήσει να καλέσει το "PyInit_foo()" για να το
αρχικοποιήσει.  Δεν συνδέετε το .exe σας με το foo.lib, καθώς αυτό θα
έκανα τα Windows να απαιτήσουν την παρουσία DLL.

Λάβετε υπόψη ότι η διαδρομή αναζήτησης για το foo.pyd είναι το
PYTHONPATH, δεν είναι ίδια με τη διαδρομή που χρησιμοποιούν τα Windows
για την αναζήτηση του foo.dll.  Επίσης, το foo.pyd δεν χρειάζεται να
υπάρχει για την εκτέλεση του προγράμματος σας, ενώ εάν συνδέσετε το
πρόγραμμά σας με ένα dll, απαιτείται το dll.  Φυσικά, απαιτείται το
foo.pyd εάν θέλετε να πείτε "import foo".  Σε ένα DLL, η σύνδεση
δηλώνεται στον πηγαίο κώδικα με το "__declspec(dllexport)". Σε ένα
.pyd, η σύνδεση ορίζεται σε μια λίστα διαθέσιμων συναρτήσεων.


Πώς μπορώ να ενσωματώσω την Python σε μια εφαρμογή Windows;
===========================================================

Η ενσωμάτωση του Python interpreter σε μια Windows εφαρμογή μπορεί να
συνοψιστεί ως εξής:

1. Να **μην** δημιουργείτε απευθείας την Python στο αρχείο σας .exe.
   Στα Windows, η Python πρέπει να είναι DLL για να χειρίζεται την
   εισαγωγή λειτουργικών μονάδων που είναι τα ίδια DLL.  (Αυτό είναι
   το πρώτο κλειδί που δεν τεκμηριώνεται.)  Αντίθετα, συνδέστε το
   "python*NN*.dll"' είναι συνήθως εγκατεστημένο στο
   "C:\Windows\System".  *NN* είναι η έκδοση Python, ένας αριθμός όπως
   "33" για Python 3.3.

   Μπορείτε να συνδεθείτε με την Python με δύο διαφορετικούς τρόπους.
   Σύνδεση χρόνου φόρτωσης σημαίνει σύνδεση ενάντια στο
   "python*NN*.lib", ενώ η σύνδεση χρόνου εκτέλεσης σημαίνει σύνδεση
   ενάντια στο "python*NN*.dll".  (Γενική σημείωση: "python*NN*.lib"
   είναι το λεγόμενο "import lib" που αντιστοιχεί στο
   "python*NN*.dll".  Απλώς ορίζει σύμβολα για το σύνδεσμο.)

   Η σύνδεση χρόνου εκτέλεσης απλοποιεί σημαντικά τις επιλογές
   συνδέσμων.  Όλα συμβαίνουν κατά την εκτέλεση.  Ο κώδικα σας πρέπει
   να φορτώσει "python*NN*.dll" χρησιμοποιώντας την ρουτίνα
   "LoadLibraryEx()" των Windows.  Ο κώδικας πρέπει επίσης να
   χρησιμοποιεί ρουτίνες πρόσβασης και δεδομένα στο "python*NN*.dll"
   (δηλαδή, το C API της Python) χρησιμοποιώντας δείκτες που
   λαμβάνονται από τη ρουτίνα των Windows "GetProcAddress()".  Οι
   μακροεντολές μπορούν να κάνουν χρησιμοποιώντας αυτούς τους δείκτες
   διαφανείς σε οποιονδήποτε κώδικα C που καλεί ρουτίνες στο C API της
   Python.

2. Εάν χρησιμοποιείτε SWIG, είναι εύκολο να δημιουργήσετε ένα Python
   "extension module" που θα κάνει τα δεδομένα και τις μεθόδους της
   εφαρμογής διαθέσιμα στην Python.  Το SWIG θα χειριστεί σχεδόν όλες
   τις grungy λεπτομέρειες για εσάς.  Το αποτέλεσμα είναι ο κώδικας C
   που συνδέεστε *στο* αρχείο σας .exe (!)  **Δεν** χρειάζεται να
   δημιουργήσετε ένα αρχείο DLL και αυτό απλοποιεί επίσης τη σύνδεση.

3. Το SWIG θα δημιουργήσει μια συνάρτηση init (μια συνάρτηση C) της
   οποία το όνομα εξαρτάται από το όνομα της μονάδας επέκτασης.  Για
   παράδειγμα, εάν το όνομά του module είναι leo, η συνάρτησης init θα
   ονομάζεται initleo().  Εάν χρησιμοποιείτε τη σκιά SWIG κλάσεις,
   όπως θα έπρεπε, η συνάρτηση init θα ονομάζεται initleoc().  Αυτό
   εκκινεί μια κυρίως κρυφή βοηθητική κλάση που χρησιμοποιείται από
   την κλάση σκιά.

   Ο λόγος για τον οποίο μπορείτε να συνδέσετε τον κώδικα C στο βήμα 2
   στο αρχείο σας .exe είναι ότι η κλήση της συνάρτησης αρχικοποίησης
   ισοδυναμεί με την εισαγωγή του module στην Python! (Αυτό είναι το
   δεύτερο κλειδί που δεν τεκμηριώνεται.)

4. Με λίγα λόγια, μπορείτε να χρησιμοποιήσετε τον ακόλουθο κώδικα για
   να αρχικοποιήσετε τον Python interpreter με το module επέκτασης.

      #include "python.h"
      ...
      Py_Initialize();  // Initialize Python.
      initmyAppc();  // Initialize (import) the helper class.
      PyRun_SimpleString("import myApp");  // Import the shadow class.

5. Υπάρχουν δύο προβλήματα με το C API της Python, τα οποία θα γίνουν
   εμφανή εάν χρησιμοποιήσετε έναν compiler διαφορετικό από τον MSVC,
   τον compiler που χρησιμοποιήθηκε για τη δημιουργία του
   pythonNN.dll.

   Πρόβλημα 1: Οι λεγόμενες συναρτήσεις "Πολύ Υψηλού Επιπέδου" που
   λαμβάνουν ορίσματα "FILE *" δεν θα λειτουργούν σε multi-compiler
   περιβάλλον, επειδή η έννοια κάθε μεταγλωττιστή για ένα "struct
   FILE" θα είναι διαφορετική.  Από την άποψη της εφαρμογής, πρόκειται
   για λειτουργίες πολύ χαμηλού επιπέδου.

   Πρόβλημα 2: Το SWIG δημιουργεί τον ακόλουθο κώδικα όταν δημιουργεί
   wrappers σε void συναρτήσεις:

      Py_INCREF(Py_None);
      _resultobj = Py_None;
      return _resultobj;

   Δυστυχώς, το Py_None είναι μια μακροεντολή που επεκτείνεται σε μια
   αναφορά σε μια σύνθετη δομή δεδομένων που ονομάζεται _Py_NoneStruct
   μέσα στο pythonNN.dll.  Και πάλι, αυτός ο κώδικας θα αποτύχει σε
   ένα mult-compiler περιβάλλον.  Αντικαταστήστε αυτόν τον κώδικα με:

      return Py_BuildValue("");

   Μπορεί να είναι δυνατή η χρήση της εντολής "%typemap" της SWIG για
   να γίνει αυτόματα η αλλαγή, αν και δεν κατάφερα να το κάνω αυτό να
   λειτουργήσει (είμαι εντελώς αρχάριος της SWIG).

6. Η χρήση ενός Python shell script για να δημιουργήσετε ένα Python
   interpreter παράθυρο μέσα από την εφαρμογή σας Windows δεν είναι
   καλή ιδέα' το παράθυρο που θα προκύψει θα είναι ανεξάρτητο από το
   σύστημα παραθύρου της εφαρμογής σας.  Αντίθετα, εσείς (ή η κλάση
   wxPythonWindow) θα πρέπει να δημιουργήσετε ένα "εγγενές" (native)
   interpreter παράθυρο.  Είναι εύκολο να συνδέσετε αυτό το παράθυρο
   με τον Python interpreter.  Μπορείτε να ανακατευθύνετε το i/o της
   Python στο _any_ αντικείμενο που υποστηρίζει ανάγνωση και εγγραφή,
   επομένως το μόνο που χρειάζεστε είναι ένα αντικείμενο Python (που
   ορίζεται στο module επέκτασης) που περιέχει τις μεθόδους read() και
   write().


Πως μπορώ να εμποδίσω τους editors να εισάγουν tabs στον πηγαίο της Python μου;
===============================================================================

Το FAQ δεν συνιστούν την χρήση καρτελών και ο οδηγός στυλ Python,
**PEP 8**, συνιστά 4 κενά για τον κατανεμημένο κώδικα Python' αυτή
είναι επίσης η προεπιλεγμένη λειτουργία python του Emacs.

Σε οποιονδήποτε editor, η μίξη tabs και spaces είναι κακή ιδέα.  Το
MSVC δεν διαφέρει από αυτή την άποψη και ρυθμίζεται εύκολα για να
χρησιμοποιεί κενά:  Πάρτε Tools ‣ Options ‣ Tabs, και για τον τύπο
αρχείου "Default" ορίστε το "Tab size" και το "Indent size" στο 4, και
επιλέξτε το κουμπί επιλογής "Insert spaces".

Η Python εγείρει το "IndentationError" ή "TabError" εάν τα μικτά tabs
και spaces προκαλούν προβλήματα στο leading whitespace. Μπορείτε
επίσης να εκτελέσετε το module "tabnanny" για να ελέγξετε εάν δέντρο
καταλόγου σε λειτουργία batch.


Πώς μπορώ να ελέγξω για ένα πάτημα πλήκτρων χωρίς αποκλεισμό;
=============================================================

Χρησιμοποιείστε το module "msvcrt".  Αυτή είναι ένα τυπικό module
επέκτασης ειδικά για τα Windows.  Ορίζει μια συνάρτηση "kbhit()" η
οποία ελέγχει εάν υπάρχει ένα χτύπημα πληκτρολογίου, και το "getch()"
παίρνει έναν χαρακτήρα χωρίς να τον επαναλαμβάνει.


Πως μπορώ να διορθώσω το σφάλμα που λείπει το api-ms-win-crt-runtime-l1-1-0.dll;
================================================================================

Αυτό μπορεί να συμβεί σε Python 3.5 και νεότερες εκδόσεις όταν
χρησιμοποιείτε Windows 8.1 ή νεότερη έκδοση χωρίς να έχουν
εγκατασταθεί όλες οι ενημερώσεις.  Πρώτα βεβαιωθείτε ότι το
λειτουργικό σας σύστημα υποστηρίζεται και είναι ενημερωμένο και εάν
αυτό δεν επιλύσει το πρόβλημα, επισκεφθείτε τη σελίδα υποστήριξης της
Microsoft για καθοδήγηση σχετικά με τη μη αυτόματη εγκατάσταση της
ενημέρωσης C Runtime.
