This document is for an old version of Python that is no longer supported. You should upgrade, and read the Python documentation for the current stable release.

# Συχνές ερωτήσεις βιβλιοθήκης και επέκτασης

Περιεχόμενα

- Συχνές ερωτήσεις βιβλιοθήκης και επέκτασης

  - Γενικές Ερωτήσεις Βιβλιοθήκης

    - Πως μπορώ να βρω ένα module ή μια εφαρμογή για να εκτελέσω την εργασία Χ;

    - Που βρίσκεται το πηγαίο αρχείο math.py (socket.py, regex.py, κ.λπ.);

    - Πως δημιουργώ ένα εκτελέσιμο Python script στο Unix;

    - Υπάρχει ένα curses/termcap πακέτο για την Python;

    - Υπάρχει κάτι ισοδύναμο με την onexit() της C στην Python;

    - Γιατί δεν λειτουργούν οι χειριστές σήματος μου;

  - Κοινές εργασίες

    - Πως μπορώ να τεστάρω ένα Python πρόγραμμα ή ένα Python component;

    - Πως δημιουργώ τεκμηρίωση από doc strings;

    - Πως μπορώ να λάβω μόνο ένα πάτημα κουμπιού κάθε φορά;

  - Νήματα (Threads)

    - Πώς μπορώ να προγραμματίσω χρησιμοποιώντας νήματα(threads);

    - Κανένα από τα νήματα (threads) μου δεν φαίνεται να εκτελείται: γιατί;

    - Πως μπορώ να μοιράσω την εργασία σε ένα σωρό από νήματα για αυτήν την εργασία;

    - Ποια είδη global μετάλλαξης τιμής είναι ασφαλή για νήμα(thread);

    - Μπορούμε να απαλλαγούμε από ένα Global Interpreter Lock;

  - Είσοδος και Έξοδος

    - Πώς μπορώ να διαγράψω ένα αρχείο; (Και άλλες ερωτήσεις για το αρχείο…)

    - Πως αντιγράφω ένα αρχείο;

    - Πώς διαβάζω (ή γράφω) δυαδικά δεδομένα;

    - Δεν μπορώ να χρησιμοποιήσω το os.read() σε ένα pipe που δημιουργήθηκε με το os.popen()∙ γιατί;

    - Πώς μπορώ να αποκτήσω πρόσβαση στη σειριακή θύρα (RS232);

    - Γιατί το κλείσιμο του sys.stdout (stdin, stderr) δεν το κλείνει πραγματικά;

  - Προγραμματισμός Δικτύου/Διαδικτύου

    - Ποια εργαλεία WWW υπάρχουν για την Python;

    - Πώς μπορώ να μιμηθώ την υποβολή φόρμας CGI (METHOD=POST);

    - Τι module πρέπει να χρησιμοποιήσω για να βοηθήσω στην δημιουργία HTML;

    - Πώς μπορώ να στείλω αλληλογραφία από ένα Python script;

    - Πώς μπορώ να αποφύγω τον αποκλεισμό στη μέθοδο connect() ενός socket;

  - Βάσεις Δεδομένων

    - Υπάρχουν διεπαφές σε πακέτα βάσεων δεδομένων στην Python;

    - Πως υλοποιείτε persistent αντικείμενα στην Python;

  - Μαθηματικά και Αριθμητικά

    - Πως μπορώ να δημιουργήσω τυχαίους αριθμούς στην Python;

## Γενικές Ερωτήσεις Βιβλιοθήκης

### Πως μπορώ να βρω ένα module ή μια εφαρμογή για να εκτελέσω την εργασία Χ;

Ελέγξτε την the Library Reference για να δείτε αν υπάρχει ένα σχετικό τυπικό module. (Τελικά θα μάθετε τι υπάρχει στην τυπική βιβλιοθήκη και θα μπορείτε να παραλείψετε αυτό το βήμα.)

For third-party packages, search the Python Package Index or try Google or another Web search engine. Searching for «Python» plus a keyword or two for your topic of interest will usually find something helpful.

### Που βρίσκεται το πηγαίο αρχείο math.py (socket.py, regex.py, κ.λπ.);

Εάν δεν μπορείτε να βρείτε ένα πηγαίο αρχείο για ένα module, μπορεί να είναι ένα ενσωματωμένο (built-in) module ή ένα module που φορτώνεται δυναμικά υλοποιημένο σε C, C++ ή άλλη μεταγλωττισμένη γλώσσα. Σε αυτή την περίπτωση μπορεί να μην έχετε το αρχείο προέλευσης ή μπορεί να είναι κάτι σαν `mathmodule.c`, κάπου σε έναν κατάλογο προέλευσης C (όχι στην διαδρομή της Python).

Υπάρχουν (το λιγότερο) τριών ειδών modules στην Python:

1. modules γραμμένα σε Python (.py):

2. modules γραμμένα σε C και φορτώνονται δυναμικά (.dll, .pyd, .so, .sl, κ.λπ.):

3. modules γραμμένα σε C και συνδεδεμένα με τον διερμηνέα: για να λάβετε μια λίστα από αυτά, πληκτρολογήστε:

       import sys
       print(sys.builtin_module_names)

### Πως δημιουργώ ένα εκτελέσιμο Python script στο Unix;

Θα πρέπει να κάνετε δύο πράγματα: η λειτουργία του script αρχείου πρέπει να είναι εκτελέσιμη και η πρώτη γραμμή θα πρέπει αν ξεκινά με `#!` ακολουθούμενη από τη διαδρομή του διερμηνέα της Python.

Το πρώτο γίνεται με την εκτέλεση του `chmod +x scriptfile` ή ίσως `chmod 755 scriptfile`.

Το δεύτερο μπορεί να γίνει με ποικίλους τρόπους. Ο πιο απλός τρόπος είναι να γράψετε

    #!/usr/local/bin/python

ως η πρώτη γραμμή του αρχείου σας, χρησιμοποιώντας το pathname για το πού είναι εγκατεστημένος ο διερμηνέας Python στην πλατφόρμα σας.

Εάν θέλετε το script να είναι ανεξάρτητο, από το που ζει ο διερμηνέας της Python, μπορείτε να χρησιμοποιήσετε το πρόγραμμα env. Σχεδόν όλες οι παραλλαγές Unix υποστηρίζουν τα ακόλουθα, υποθέτοντας ότι ο διερμηνέας Python βρίσκεται σε έναν κατάλογο στο `PATH` του χρήστη:

    #!/usr/bin/env python

Μην το κάνετε αυτό για CGI scripts. Η μεταβλητή `PATH` για τα CGI scripts είναι συχνά πολύ ελάχιστη, επομένως πρέπει να χρησιμοποιήσετε το πραγματικό απόλυτο όνομα διαδρομής του διερμηνέα.

Περιστασιακά, το περιβάλλον ενός χρήστη είναι τόσο γεμάτο που το πρόγραμμα /usr/bin/env αποτυγχάνει ή δεν υπάρχει καθόλου πρόγραμμα env. Σε αυτήν την περίπτωση, μπορείτε να δοκιμάσετε το ακόλουθο hack (λόγω του Alex Rezinsky):

    #! /bin/sh
    """:"
    exec python $0 ${1+"$@"}
    """

Το, ελάχιστης σημασίας, μειονέκτημα είναι ότι αυτό καθορίζει τη συμβολοσειρά __doc__ του script. Ωστόσο, μπορείτε να το διορθώσετε προσθέτοντας

    __doc__ = """...Whatever..."""

### Υπάρχει ένα curses/termcap πακέτο για την Python;

Για παραλλαγές Unix: Η τυπική διανομή του πηγαίου της Python συνοδεύεται από ένα curses module στον υποκατάλογο Modules, αν και δεν έχει μεταγλωττιστεί από προεπιλογή. (Λάβετε υπόψη ότι αυτό δεν είναι διαθέσιμο στη διανομή των Windows – δεν υπάρχει curses module για Windows.)

Το module `curses` υποστηρίζει βασικές curses λειτουργίες καθώς και πολλές πρόσθετες λειτουργίες από ncurses και SYSV curses, όπως χρώμα, υποστήριξη εναλλακτικού συνόλου χαρακτήρων, pads και υποστήριξη ποντικιού. Αυτό σημαίνει ότι το module δεν είναι συμβατό με λειτουργικά συστήματα που έχουνε μόνο BSD curses, αλλά δεν φαίνεται να υπάρχουν επί του παρόντος διατηρημένα λειτουργικά συστήματα που να εμπίπτουν σε αυτήν την κατηγορία.

### Υπάρχει κάτι ισοδύναμο με την onexit() της C στην Python;

The `atexit` module provides a register function that is similar to C’s `onexit()`.

### Γιατί δεν λειτουργούν οι χειριστές σήματος μου;

Το πιο συνηθισμένο πρόβλημα είναι ότι ο χειριστής σήματος δηλώνεται με λάθος λίστα ορισμάτων. Ονομάζεται ως

    handler(signum, frame)

οπότε θα πρέπει να δηλωθεί με δύο παραμέτρους:

    def handler(signum, frame):
        ...

## Κοινές εργασίες

### Πως μπορώ να τεστάρω ένα Python πρόγραμμα ή ένα Python component;

Η Python συνοδεύεται από δύο frameworks για τεστ. To module `doctest` βρίσκει παραδείγματα στα docstrings για ένα module και τα εκτελεί, συγκρίνοντας την έξοδο με την αναμενόμενη έξοδο που δίνεται στο docstring.

Το module `unittest` είναι ένα πιο εντυπωσιακό framework που έχει σχεδιαστεί με βάση τα frameworks για τεστ της Java και του Smalltalk.

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

Η «παγκόσμια κύρια λογική» του προγράμματος σας μπορεί να είναι τόσο απλή όσο

    if __name__ == "__main__":
        main_logic()

στο κάτω μέρος του κύριου module τους προγράμματός σας.

Από τη στιγμή που το πρόγραμμα σας οργανωθεί ως μια συλλογή από συναρτήσεις και κλάσεις που υλοποιούν μια διαδικασία, θα πρέπει να γράψετε τεστ συναρτήσεις που εκτελούν τις αντίστοιχες διαδικασίες. Μια τεστ σουίτα που αυτοματοποιεί μια ακολουθία από tests μπορεί να συσχετιστεί με κάθε module. Αυτό ακούγεται σαν πολλή δουλειά, αλλά επειδή η Python είναι τόσο σύντομη και ευέλικτη, αυτό είναι εκπληκτικά εύκολο. Μπορείτε να κάνετε την συγγραφή κώδικα πολύ πιο ευχάριστη και διασκεδαστική γράφοντας τις δοκιμαστικές συναρτήσεις σας παράλληλα με τον «κώδικα παραγωγής», καθώς αυτό διευκολύνει την εύρεση σφαλμάτων και ακόμη και ελαττώματα σχεδιασμού νωρίτερα.

«Modules υποστήριξης» που δεν προορίζονται να είναι το κύριο module ενός προγράμματος μπορεί να περιλαμβάνουν αυτοέλεγχο της ενότητας:

    if __name__ == "__main__":
        self_test()

Ακόμη και προγράμματα που αλληλεπιδρούν με πολύπλοκες εξωτερικές διεπαφές μπορούν να δοκιμαστούν όταν οι εξωτερικές διεπαφές δεν είναι διαθέσιμες χρησιμοποιώντας «τεχνητές» διεπαφές υλοποιημένες στην Python.

### Πως δημιουργώ τεκμηρίωση από doc strings;

The `pydoc` module can create HTML from the doc strings in your Python source code. An alternative for creating API documentation purely from docstrings is epydoc. Sphinx can also include docstring content.

### Πως μπορώ να λάβω μόνο ένα πάτημα κουμπιού κάθε φορά;

Για τις παραλλαγές του Unix υπάρχουν πολλές λύσεις. Είναι απλό να κάνετε αυτό χρησιμοποιώντας curses, αλλά τα curses είναι ένα αρκετά μεγάλο module για εκμάθηση.

## Νήματα (Threads)

### Πώς μπορώ να προγραμματίσω χρησιμοποιώντας νήματα(threads);

Βεβαιωθείτε ότι χρησιμοποιείτε το module `threading` και όχι το module `_thread`. Το module `threading` παρέχει ένα πιο βολικό και υψηλού επιπέδου τρόπο διαχείρισης νημάτων, χτίζοντας πάνω στις βασικές λειτουργίες του module `_thread`.

### Κανένα από τα νήματα (threads) μου δεν φαίνεται να εκτελείται: γιατί;

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

Μια απλή λύση είναι να προσθέσετε ένα sleep στο τέλος που προγράμματος που είναι αρκετό για να τερματιστούν όλα τα νήματα:

    import threading, time

    def thread_task(name, n):
        for i in range(n):
            print(name, i)

    for i in range(10):
        T = threading.Thread(target=thread_task, args=(str(i), i))
        T.start()

    time.sleep(10)  # <---------------------------!

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

Μια απλή λύση είναι να προσθέσετε ένα μικρό sleep στην αρχή της λειτουργίας εκτέλεσης:

    def thread_task(name, n):
        time.sleep(0.001)  # <--------------------!
        for i in range(n):
            print(name, i)

    for i in range(10):
        T = threading.Thread(target=thread_task, args=(str(i), i))
        T.start()

    time.sleep(10)

Αντί να προσπαθείτε να μαντέψετε μια καλή τιμή καθυστέρησης για την `time.sleep()`, είναι καλύτερα να χρησιμοποιείτε κάποιο είδος μηχανισμού σηματοφόρου. Μια ιδέα είναι να χρησιμοποιήσετε το module `queue` για να δημιουργήσετε ένα αντικείμενο ουράς, αφήνοντας το κάθε νήμα να προσθέτει ένα token στην ουρά όταν ολοκληρωθεί, και να αφήνει στο κύριο νήμα να διαβάσει τόσα tokens από την ουρά όσα είναι και τα νήματα.

### Πως μπορώ να μοιράσω την εργασία σε ένα σωρό από νήματα για αυτήν την εργασία;

Ο ευκολότερο τρόπος είναι να χρησιμοποιήσετε το module `concurrent.futures`, ειδικά την κλάση `ThreadPoolExecutor`.

Ή, ένα θέλετε καλό έλεγχο στον αλγόριθμο αποστολής, μπορείτε να γράψετε τη δική σας λογική με μη αυτόματο τρόπο. Χρησιμοποιήστε το module `queue` για να δημιουργήσετε μια ουρά που περιέχει μια λίστα εργασιών. Η κλάση `Queue` διατηρεί μια λίστα αντικειμένων και έχει μια μέθοδο `.put(obj)` που προσθέτει στοιχεία στην ουρά και μια μέθοδο `.get()` για επιστροφή. Η κλάση θα φροντίσει για το κλείδωμα που είναι απαραίτητο για να διασφαλίσει ότι κάθε εργασία θα παραδοθεί ακριβώς μία φορά.

Ένα απλό παράδειγμα:

    import threading, queue, time

    # The worker thread gets jobs off the queue.  When the queue is empty, it
    # assumes there will be no more work and exits.
    # (Realistically workers will run until terminated.)
    def worker():
        print('Running worker')
        time.sleep(0.1)
        while True:
            try:
                arg = q.get(block=False)
            except queue.Empty:
                print('Worker', threading.currentThread(), end=' ')
                print('queue empty')
                break
            else:
                print('Worker', threading.currentThread(), end=' ')
                print('running with argument', arg)
                time.sleep(0.5)

    # Create queue
    q = queue.Queue()

    # Start a pool of 5 workers
    for i in range(5):
        t = threading.Thread(target=worker, name='worker %i' % (i+1))
        t.start()

    # Begin adding work to the queue
    for i in range(50):
        q.put(i)

    # Give threads time to run
    print('Main thread sleeping')
    time.sleep(5)

Κατά την εκτέλεση, αυτό θα παράγει την ακόλουθη έξοδο:

    Running worker
    Running worker
    Running worker
    Running worker
    Running worker
    Main thread sleeping
    Worker <Thread(worker 1, started 130283832797456)> running with argument 0
    Worker <Thread(worker 2, started 130283824404752)> running with argument 1
    Worker <Thread(worker 3, started 130283816012048)> running with argument 2
    Worker <Thread(worker 4, started 130283807619344)> running with argument 3
    Worker <Thread(worker 5, started 130283799226640)> running with argument 4
    Worker <Thread(worker 1, started 130283832797456)> running with argument 5
    ...

Συμβουλευτείτε την τεκμηρίωση του module για περισσότερες λεπτομέρειες· η κλάση `Queue` παρέχει μια χαρακτηριστική διεπαφή.

### Ποια είδη global μετάλλαξης τιμής είναι ασφαλή για νήμα(thread);

Ένα global interpreter lock (GIL) χρησιμοποιείται εσωτερικά για να διασφαλιστεί ότι μόνο ένα νήμα εκτελείται στο Python VM κάθε φορά. Γενικά, η Python προσφέρει εναλλαγή μεταξύ νημάτων μόνο μεταξύ εντολών bytecode· το πόσο συχνά γίνεται αυτή η εναλλαγή καθορίζεται από την `sys.setswitchinterval()`. Κάθε εντολή bytecode και επομένως όλος ο κώδικας υλοποίησης C που φτάνει από κάθε εντολή είναι επομένως ατομικός από την άποψη ενός προγράμματος Python.

Θεωρητικά, αυτό σημαίνει ότι μια ακριβώς λογιστική απαιτεί ακριβή κατανόηση της εφαρμογής bytecode PVM. Στην πράξη, σημαίνει ότι οι λειτουργίες σε κοινόχρηστες μεταβλητές ενσωματωμένων δεδομένων (ακέραιοι, λίστες, λεξικά, κ.λπ.) που «φαίνονται ατομικά» πραγματικά είναι.

Για παράδειγμα, οι ακόλουθες πράξεις είναι όλες ατομικές (L, L1, L2 είναι λίστες, D, D1, D2 είναι λεξικά, x, y είναι αντικείμενα, i, j είναι ακέραιοι):

    L.append(x)
    L1.extend(L2)
    x = L[i]
    x = L.pop()
    L1[i:j] = L2
    L.sort()
    x = y
    x.field = y
    D[x] = y
    D1.update(D2)
    D.keys()

Αυτά δεν είναι:

    i = i+1
    L.append(L[-1])
    L[i] = L[j]
    D[x] = D[x] + 1

Operations that replace other objects may invoke those other objects” `__del__()` method when their reference count reaches zero, and that can affect things. This is especially true for the mass updates to dictionaries and lists. When in doubt, use a mutex!

### Μπορούμε να απαλλαγούμε από ένα Global Interpreter Lock;

Το global interpreter lock (GIL) θεωρείται συχνά ως εμπόδιο για την ανάπτυξη της Python σε υψηλής τεχνολογίας μηχανήματα διακομιστών με πολυεπεξεργαστές, επειδή ένα πρόγραμμα Python με πολλά νήματα χρησιμοποιεί αποτελεσματικά μόνο μία CPU, λόγω της επιμονής ότι (σχεδόν) όλος ο κώδικας της Python μπορεί να εκτελεστεί μόνο όσο διατηρείται το GIL.

Πίσω στις μέρες της Python 1.5, ο Greg Stein υλοποίησε πραγματικά ένα ολοκληρωμένο σύνολο επιδιορθώσεων (οι επιδιορθώσεις «ελεύθερου νήματος») που αφαίρεσε το GIL και το αντικατέστησε με ένα άριστα προσεγμένο κλειδωμένο thread. Ο Adam Olsen έκανε πρόσφατα ένα παρόμοιο πείραμα στο έργο python-safethread. Δυστυχώς, και τα δύο πειράματα εμφάνισαν απότομη πτώση στην απόδοση ενός νήματος (τουλάχιστον 30% πιο αργή), λόγω της ποσότητας του προσεγμένου κλειδώματος που απαιτείται για την αντιστάθμιση της αφαίρεσης του GIL.

Αυτό δεν σημαίνει ότι δεν μπορείτε να κάνετε καλή χρήση της Python σε μηχανήματα πολλαπλών επεξεργαστών! Απλώς πρέπει να είστε δημιουργικοί μοιράζοντας την εργασία μεταξύ πολλαπλών διεργασιών και όχι πολλών νημάτων. Η κλάση `ProcessPoolExecutor` στο νέο module `concurrent.futures`, παρέχει έναν εύκολο τρόπο για να το κάνετε αυτό· Το module `multiprocessing` παρέχει ένα API χαμηλότερου επιπέδου σε περίπτωση που θέλετε περισσότερο έλεγχο στην αποστολή των εργασιών.

Η συνετή χρήση των επεκτάσεων C βοηθάει επίσης· εάν χρησιμοποιείτε μια επέκταση C για να εκτελέσετε μια χρονοβόρα εργασία, η επέκταση μπορεί να απελευθερώσει το GIL ενώ το νήμα εκτέλεσης βρίσκεται στον κώδικα C και να επιτρέψει σε άλλα νήματα να ολοκληρώσουν κάποια εργασία. Ορισμένα τυπικά module βιβλιοθήκης όπως `zlib` και `hashlib` το κάνουν ήδη αυτό.

Έχει προταθεί ότι το GIL θα πρέπει να είναι ένα κλείδωμα ανά κατάσταση διερμηνέα αντί να είναι πραγματικά καθολικό∙ τότε οι διερμηνείς δεν θα μπορούν να μοιράζονται αντικείμενα. Δυστυχώς, ούτε αυτό είναι πιθανό να συμβεί. Θα ήταν τεράστιος όγκος δουλειάς, επειδή πολλές υλοποιήσεις αντικειμένων επί του παρόντος έχουν παγκόσμια κατάσταση. Για παράδειγμα, μικροί ακέραιοι αριθμοί και σύντομες συμβολοσειρές αποθηκεύονται στην κρυφή μνήμη∙ αυτές οι κρυφές μνήμες θα πρέπει να μετακινηθούν στην κατάσταση διερμηνέα. Άλλοι τύποι αντικειμένων έχουν τη δική τους κενή λίστα∙ αυτές οι κενές λίστες θα πρέπει να μετακινηθούν στην κατάσταση διερμηνέα. Και ούτω καθεξής.

Και αμφιβάλλω ότι μπορεί να γίνει ακόμη και σε πεπερασμένο χρόνο, επειδή το ίδιο πρόβλημα υπάρχει για τις επεκτάσεις τρίτων. Είναι πιθανό ότι οι επεκτάσεις τρίτων γράφονται με ταχύτερο ρυθμό από ό,τι μπορείτε να τις μετατρέψετε για να αποθηκεύσετε όλη την καθολική τους κατάσταση στην κατάσταση διερμηνέα.

Και τέλος, από τη στιγμή που έχετε πολλούς διερμηνείς που δεν μοιράζονται καμία κατάσταση, τι έχετε κερδίσει από τη λειτουργία κάθε διερμηνέα σε μια ξεχωριστή διαδικασία;

## Είσοδος και Έξοδος

### Πώς μπορώ να διαγράψω ένα αρχείο; (Και άλλες ερωτήσεις για το αρχείο…)

Χρησιμοποιήστε τα `os.remove(filename)` ή `os.unlink(filename)` ∙ για τεκμηρίωση, ανατρέξτε στο module `os`. Οι δύο συναρτήσεις είναι ίδιες∙ η `unlink()` είναι απλώς το όνομα της κλήσης συστήματος Unix για αυτήν τη λειτουργία.

Για να καταργήσετε έναν κατάλογο, χρησιμοποιήστε τη `os.rmdir()` ∙ χρησιμοποιήστε τη `os.mkdir()` για να δημιουργήσετε έναν. Το `os.makedirs(path)` θα δημιουργήσει τυχόν ενδιάμεσους καταλόγους στο `path` που δεν υπάρχουν. Το `os.removedirs(path)` θα αφαιρέσει τους ενδιάμεσους καταλόγους εφόσον είναι κενοί∙ εάν θέλετε να διαγράψετε ολόκληρο δέντρο καταλόγου και τα περιεχόμενα του, χρησιμοποιήστε τη `shutil.rmtree()`.

Για να μετονομάσετε ένα αρχείο, χρησιμοποιήστε το `os.rename(old_path, new_path)`.

Για να περικόψετε ένα αρχείο, ανοίξτε το χρησιμοποιώντας `f = open(filename, "rb+")`, και χρησιμοποιήστε το `f.truncate(offset)` ∙ μετατόπιση των προεπιλογών στην τρέχουσα θέση αναζήτησης. Υπάρχει επίσης το `os.ftruncate(fd, offset)` για αρχεία που ανοίγουν με `os.open()`, όπου fd είναι ο περιγραφέας αρχείου (ένας μικρός ακέραιος).

Το module `shutil` περιέχει επίσης έναν αριθμό λειτουργιών για εργασία σε αρχεία, όπως `copyfile()`, `copytree()`, και `rmtree()`.

### Πως αντιγράφω ένα αρχείο;

The `shutil` module contains a `copyfile()` function. Note that on MacOS 9 it doesn’t copy the resource fork and Finder info.

### Πώς διαβάζω (ή γράφω) δυαδικά δεδομένα;

Για να διαβάσετε ή να γράψετε σύνθετες μορφές δυαδικών δεδομένων, είναι καλύτερο να χρησιμοποιήσετε το module `struct`. Σας επιτρέπει να πάρετε μια συμβολοσειρά που περιέχει δυαδικά δεδομένα (συνήθως αριθμούς) και να τη μετατρέψετε σε αντικείμενα Python και αντίστροφα.

Για παράδειγμα, ο παρακάτω κώδικας διαβάζει δύο ακέραιους αριθμούς 2 byte και έναν ακέραιο αριθμό 4 byte σε μορφή big-endian από ένα αρχείο:

    import struct

    with open(filename, "rb") as f:
        s = f.read(8)
        x, y, z = struct.unpack(">hhl", s)

Το “>” στη συμβολοσειρά μορφής αναγκάζει δεδομένα big-endian∙ το γράμμα “h” διαβάζει έναν «short integer» (2 bytes), και το “l” διαβάζει έναν «long integer» (4 byte) από την συμβολοσειρά.

Για δεδομένα που είναι πιο κανονικά (π.χ. μια ομοιογενής λίστα ακεραίων ή αριθμούς με υποδιαστολή), μπορείτε επίσης να χρησιμοποιήσετε το module `array`.

Σημείωση

Για να διαβάσετε και να γράψετε δυαδικά δεδομένα, είναι υποχρεωτικό να ανοίξετε το αρχείο σε δυαδική λειτουργία (εδώ, περνώντας το `"rb"` στη `open()`). Εάν χρησιμοποιήσετε το `"r"` αντί αυτού (προεπιλεγμένο) το αρχείο θα είναι ανοιχτό σε λειτουργία κειμένου και το `f.read()` θα επιστρέψει αντικείμενα `str` αντί για αντικείμενα `bytes`.

### Δεν μπορώ να χρησιμοποιήσω το os.read() σε ένα pipe που δημιουργήθηκε με το os.popen()∙ γιατί;

Η `os.read()` είναι μια συνάρτηση χαμηλού επιπέδου που παίρνει έναν περιγραφέα αρχείου, έναν μικρό ακέραιο που αντιπροσωπεύει το ανοιχτό αρχείο. Η `os.popen()` δημιουργεί ένα αντικείμενο αρχείου υψηλού επιπέδου, του ίδιου τύπου που επιστρέφεται από την ενσωματωμένη συνάρτηση `open()`. Έτσι, για να διαβάσετε n byte από ένα pipe p που δημιουργήθηκε με τη `os.popen()`, πρέπει να χρησιμοποιήσετε το `p.read(n)`.

### Πώς μπορώ να αποκτήσω πρόσβαση στη σειριακή θύρα (RS232);

Για Win32, OSX, Linux, BSD, Jython, IronPython:

> https://pypi.org/project/pyserial/

Για το Unix, δείτε μια ανάρτηση στο Usenet από τον Mitch Chapman:

> https://groups.google.com/groups?selm=34A04430.CF9@ohioee.com

### Γιατί το κλείσιμο του sys.stdout (stdin, stderr) δεν το κλείνει πραγματικά;

Το Python file objects είναι ένα επίπεδο αφαίρεσης υψηλού επιπέδου σε χαμηλού επιπέδου περιγραφείς αρχείων C.

Για τα περισσότερα αντικείμενα αρχείων που δημιουργείτε στην Python μέσω της ενσωματωμένης συνάρτησης `open()`, η `f.close()` επισημαίνει το αντικείμενο αρχείου Python ως κλειστό από την άποψη της Python και επίσης κανονίζει να κλείσει ο υποκείμενος περιγραφέας αρχείου C. Αυτό συμβαίνει επίσης αυτόματα στον καταστροφέα του `f`, όταν το `f` γίνεται σκουπίδια.

Αλλά τα stdin, stdout και stderr αντιμετωπίζονται ειδικά από την Python, λόγω της ειδικής κατάστασης που τους δίνεται επίσης από τη C. Εκτελώντας το `sys.stdout.close()` επισημαίνει το αντικείμενο αρχείου σε επίπεδο Python ως κλειστό, αλλά δεν κλείνει το συσχετισμένο περιγραφικό αρχείου C.

Για να κλείσετε τον υποκείμενο περιγραφέα αρχείου C για ένα από αυτά τα τρία, θα πρέπει πρώτα να βεβαιωθείτε ότι αυτό θέλετε πραγματικά να κάνετε (π.χ., μπορείτε να μπερδέψετε τα modules επέκτασης που προσπαθούν να κάνουν I/O). Εάν είναι, χρησιμοποιήστε τη `os.close()`:

    os.close(stdin.fileno())
    os.close(stdout.fileno())
    os.close(stderr.fileno())

Ή μπορείτε να χρησιμοποιήσετε τις αριθμητικές σταθερές 0, 1 και 2, αντίστοιχα.

## Προγραμματισμός Δικτύου/Διαδικτύου

### Ποια εργαλεία WWW υπάρχουν για την Python;

Δείτε τα κεφάλαια με τίτλο Πρωτόκολλα Internet και Υποστήριξη και Internet Data Handling στο Εγχειρίδιο Αναφοράς Βιβλιοθήκης. Η Python έχει πολλά modules που θα σας βοηθήσουν να δημιουργήσετε συστήματα ιστού από την πλευρά του διακομιστή και του πελάτη.

Μια σύνοψη των διαθέσιμων πλαισίων διατηρείται από τον Paul Boddie στη διεύθυνση https://wiki.python.org/moin/WebProgramming.

Cameron Laird maintains a useful set of pages about Python web technologies at http://phaseit.net/claird/comp.lang.python/web_python.

### Πώς μπορώ να μιμηθώ την υποβολή φόρμας CGI (METHOD=POST);

Θα ήθελα να ανακτήσω ιστοσελίδες που είναι αποτέλεσμα του POST μιας φόρμας. Υπάρχει κώδικας που θα επέτρεπε να το κάνω εύκολα;

Ναι. Ακολουθεί ένα απλό παράδειγμα που χρησιμοποιεί `urllib.request`:

    #!/usr/local/bin/python

    import urllib.request

    # build the query string
    qs = "First=Josephine&MI=Q&Last=Public"

    # connect and send the server a path
    req = urllib.request.urlopen('http://www.some-server.out-there'
                                 '/cgi-bin/some-cgi-script', data=qs)
    with req:
        msg, hdrs = req.read(), req.info()

Λάβετε υπόψιν ότι γενικά για λειτουργίες POST με κωδικοποίηση ποσοστού, οι συμβολοσειρές ερωτημάτων πρέπει να αναφέρονται χρησιμοποιώντας τη `urllib.parse.urlencode()`. Για παράδειγμα, για να στείλετε `name=Guy Steele, Jr.`:

    >>> import urllib.parse
    >>> urllib.parse.urlencode({'name': 'Guy Steele, Jr.'})
    'name=Guy+Steele%2C+Jr.'

Δείτε επίσης

HOWTO Fetch Internet Resources Using The urllib Package για εκτενή παραδείγματα.

### Τι module πρέπει να χρησιμοποιήσω για να βοηθήσω στην δημιουργία HTML;

Μπορείτε να βρείτε μια συλλογή από χρήσιμους συνδέσμους στη σελίδα Web Programming wiki page.

### Πώς μπορώ να στείλω αλληλογραφία από ένα Python script;

Χρησιμοποιήστε την τυπική module βιβλιοθήκη `smtplib`.

Εδώ είναι ένας πολύ απλός διαδραστικός αποστολέας αλληλογραφίας που τον χρησιμοποιεί. Αυτή η μέθοδος θα λειτουργήσει σε οποιονδήποτε κεντρικό υπολογιστή υποστηρίζει το πρόγραμμα ακρόασης SMTP.

    import sys, smtplib

    fromaddr = input("From: ")
    toaddrs  = input("To: ").split(',')
    print("Enter message, end with ^D:")
    msg = ''
    while True:
        line = sys.stdin.readline()
        if not line:
            break
        msg += line

    # The actual mail send
    server = smtplib.SMTP('localhost')
    server.sendmail(fromaddr, toaddrs, msg)
    server.quit()

Μια εναλλακτική λύση μόνο για Unix χρησιμοποιεί sendmail. Η τοποθεσία του προγράμματος sendmail ποικίλλει μεταξύ των συστημάτων∙ μερικές φορές είναι `/usr/lib/sendmail`, μερικές φορές `/usr/sbin/sendmail`. Η σελίδα εγχειριδίου sendmail θα σας βοηθήσει. Ορίστε ένα δείγμα κώδικα:

    import os

    SENDMAIL = "/usr/sbin/sendmail"  # sendmail location
    p = os.popen("%s -t -i" % SENDMAIL, "w")
    p.write("To: receiver@example.com\n")
    p.write("Subject: test\n")
    p.write("\n")  # blank line separating headers from body
    p.write("Some text\n")
    p.write("some more text\n")
    sts = p.close()
    if sts != 0:
        print("Sendmail exit status", sts)

### Πώς μπορώ να αποφύγω τον αποκλεισμό στη μέθοδο connect() ενός socket;

Το module `select` χρησιμοποιείται συνήθως για να βοηθήσει με ασύγχρονες I/O σε sockets.

To prevent the TCP connect from blocking, you can set the socket to non-blocking mode. Then when you do the `socket.connect()`, you will either connect immediately (unlikely) or get an exception that contains the error number as `.errno`. `errno.EINPROGRESS` indicates that the connection is in progress, but hasn’t finished yet. Different OSes will return different values, so you’re going to have to check what’s returned on your system.

You can use the `socket.connect_ex()` method to avoid creating an exception. It will just return the errno value. To poll, you can call `socket.connect_ex()` again later – `0` or `errno.EISCONN` indicate that you’re connected – or you can pass this socket to `select.select()` to check if it’s writable.

Σημείωση

The `asyncio` module provides a general purpose single-threaded and concurrent asynchronous library, which can be used for writing non-blocking network code. The third-party Twisted library is a popular and feature-rich alternative.

## Βάσεις Δεδομένων

### Υπάρχουν διεπαφές σε πακέτα βάσεων δεδομένων στην Python;

Ναι.

Διεπαφές σε κατακερματισμούς που βασίζονται σε δίσκο, όπως `DBM` και `GDBM` περιλαμβάνονται επίσης στην τυπική Python. Υπάρχει επίσης το module `sqlite3`, το οποίο παρέχει μια ελαφριά σχεσιακή βάση δεδομένων που βασίζεται στο δίσκο.

Υποστήριξη για τις περισσότερες σχεσιακές βάσεις δεδομένων είναι διαθέσιμη. Δείτε τη σελίδα DatabaseProgramming wiki page για λεπτομέρειες.

### Πως υλοποιείτε persistent αντικείμενα στην Python;

To module βιβλιοθήκης `pickle` το λύνει αυτό με πολύ γενικό τρόπο (αν και δεν μπορείτε ακόμα να αποθηκεύσετε πράγματα όπως ανοιχτά αρχεία, sockets ή παράθυρα), και το module βιβλιοθήκης `shelve` χρησιμοποιεί pickle και (g)dbm για τη δημιουργία επίμονων αντιστοιχίσεων που περιέχουν αυθαίρετα αντικείμενα Python.

## Μαθηματικά και Αριθμητικά

### Πως μπορώ να δημιουργήσω τυχαίους αριθμούς στην Python;

Η τυπική ενότητα `random` υλοποιεί μια γεννήτρια τυχαίων αριθμών. Η χρήση είναι απλή:

    import random
    random.random()

This returns a random floating point number in the range [0, 1).

Υπάρχουν επίσης πολλές άλλες εξειδικευμένες γεννήτριες σε αυτό το module, όπως:

- Το `randrange(a, b)` επιλέγει έναν ακέραιο στο εύρος [a, b).

- `uniform(a, b)` chooses a floating point number in the range [a, b).

- Το `normalvariate(mean, sdev)` λαμβάνει δείγματα της κανονικής (Gaussian) κατανομής.

Ορισμένες συναρτήσεις υψηλότερου επιπέδου λειτουργούν απευθείας σε ακολουθίες, όπως:

- To `choice(S)` επιλέγει ένα τυχαίο στοιχείο από μια δεδομένη ακολουθία.

- Το `shuffle(L)` ανακατεύει μια λίστα επιτόπου, δηλαδή τη μεταθέτει τυχαία.

Υπάρχει επίσης μια κλάση `Random` που μπορείτε να επιβεβαιώσετε για να δημιουργήσετε ανεξάρτητες γεννήτριες πολλαπλών τυχαίων αριθμών.