ライブラリと拡張に関するFAQ—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/faq/library
移動先:案内検索

ライブラリと拡張機能に関するFAQ

コンテンツ


図書館に関する一般的な質問

タスクXを実行するモジュールまたはアプリケーションを見つけるにはどうすればよいですか?

ライブラリリファレンスをチェックして、関連する標準ライブラリモジュールがあるかどうかを確認してください。 (最終的には、標準ライブラリの内容を学習し、この手順をスキップできるようになります。)

サードパーティのパッケージについては、 Python Package Index を検索するか、 Google または別のWeb検索エンジンを試してください。 「Python」に加えて、関心のあるトピックのキーワードを1つか2つ検索すると、通常、役立つものが見つかります。


math.py(socket.py、regex.pyなど)のソースファイルはどこにありますか?

モジュールのソースファイルが見つからない場合は、C、C ++、またはその他のコンパイル言語で実装された組み込みモジュールまたは動的にロードされたモジュールである可能性があります。 この場合、ソースファイルがないか、mathmodule.cのようなCソースディレクトリのどこかにある可能性があります(Pythonパス上ではありません)。

Pythonには(少なくとも)3種類のモジュールがあります。

  1. Python(.py)で記述されたモジュール。

  2. Cで記述され、動的にロードされるモジュール(.dll、.pyd、.so、.slなど)。

  3. Cで記述され、インタープリターにリンクされたモジュール。 これらのリストを取得するには、次のように入力します。

    import sys
    print sys.builtin_module_names


UnixでPythonスクリプトを実行可能にするにはどうすればよいですか?

スクリプトファイルのモードは実行可能である必要があり、最初の行は#!で始まり、その後にPythonインタープリターのパスが続く必要があります。

1つ目は、chmod +x scriptfileまたはおそらくchmod 755 scriptfileを実行することによって実行されます。

2つ目は、さまざまな方法で実行できます。 最も簡単な方法は書くことです

#!/usr/local/bin/python

ファイルの最初の行として、Pythonインタープリターがプラットフォームにインストールされている場所のパス名を使用します。

Pythonインタープリターが存在する場所からスクリプトを独立させたい場合は、 env プログラムを使用できます。 Pythonインタープリターがユーザーの PATHのディレクトリにあると仮定すると、ほとんどすべてのUnixバリアントは以下をサポートします。

#!/usr/bin/env python

CGIスクリプトに対してこれを行わないでください。 CGIスクリプトの PATH変数は非常に小さいことが多いため、インタープリターの実際の絶対パス名を使用する必要があります。

時折、ユーザーの環境がいっぱいになり、 / usr / bin / env プログラムが失敗することがあります。 または、envプログラムがまったくありません。 その場合、次のハックを試すことができます(Alex Rezinskyによる):

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

マイナーな欠点は、これがスクリプトの__doc__文字列を定義することです。 ただし、追加することで修正できます

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

Python用のcurses / termcapパッケージはありますか?

Unixバリアントの場合、標準のPythonソースディストリビューションには:source: `Modules` サブディレクトリにcursesモジュールが付属していますが、デフォルトではコンパイルされていません。 (これはWindowsディストリビューションでは利用できないことに注意してください– Windows用のcursesモジュールはありません。)

curses モジュールは、基本的なcurses機能に加えて、色、代替文字セットのサポート、パッド、マウスのサポートなど、ncursesおよびSYSVcursesからの多くの追加機能をサポートします。 これは、モジュールがBSDの呪いしかないオペレーティングシステムと互換性がないことを意味しますが、このカテゴリに分類される現在保守されているOSはないようです。

Windowsの場合: consolelibモジュールを使用します。


PythonにCのonexit()に相当するものはありますか?

atexit モジュールは、Cのonexit()と同様のレジスタ機能を提供します。


シグナルハンドラが機能しないのはなぜですか?

最も一般的な問題は、シグナルハンドラが間違った引数リストで宣言されていることです。 それはとして呼ばれます

handler(signum, frame)

したがって、2つの引数で宣言する必要があります。

def handler(signum, frame):
    ...

一般的なタスク

Pythonプログラムまたはコンポーネントをテストするにはどうすればよいですか?

Pythonには2つのテストフレームワークが付属しています。 doctest モジュールは、モジュールのdocstringで例を見つけて実行し、出力をdocstringで指定された期待される出力と比較します。

unittest モジュールは、JavaおよびSmalltalkテストフレームワークをモデルにした、より洗練されたテストフレームワークです。

テストを簡単にするには、プログラムで優れたモジュラー設計を使用する必要があります。 プログラムには、関数またはクラスメソッドのいずれかにカプセル化されたほぼすべての機能が必要です。これにより、プログラムの実行速度が向上するという驚くべき楽しい効果が得られる場合があります(ローカル変数アクセスはグローバルアクセスよりも高速であるため)。 さらに、プログラムはグローバル変数の変更に依存することを避ける必要があります。これにより、テストがはるかに困難になるためです。

プログラムの「グローバルメインロジック」は、次のように単純な場合があります。

if __name__ == "__main__":
    main_logic()

プログラムのメインモジュールの下部にあります。

プログラムが関数とクラスの動作の扱いやすいコレクションとして編成されたら、動作を実行するテスト関数を作成する必要があります。 一連のテストを自動化するテストスイートを各モジュールに関連付けることができます。 これは大変な作業のように聞こえますが、Pythonは非常に簡潔で柔軟性があるため、驚くほど簡単です。 「本番コード」と並行してテスト関数を作成することで、コーディングをより楽しく楽しくすることができます。これにより、バグや設計上の欠陥を早期に見つけることが容易になります。

プログラムのメインモジュールとなることを意図していない「サポートモジュール」には、モジュールのセルフテストが含まれる場合があります。

if __name__ == "__main__":
    self_test()

複雑な外部インターフェースと相互作用するプログラムでさえ、Pythonで実装された「偽の」インターフェースを使用して、外部インターフェースが利用できない場合にテストされる可能性があります。


ドキュメント文字列からドキュメントを作成するにはどうすればよいですか?

pydoc モジュールは、Pythonソースコードのドキュメント文字列からHTMLを作成できます。 純粋にdocstringからAPIドキュメントを作成するための代替手段は、 epidoc です。 Sphinx には、docstringコンテンツを含めることもできます。


一度に1回キーを押すにはどうすればよいですか?

Unixバリアントには、いくつかの解決策があります。 cursesを使用してこれを行うのは簡単ですが、cursesは学ぶのにかなり大きなモジュールです。 これが呪いのない解決策です:

import termios, fcntl, sys, os
fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
    while 1:
        try:
            c = sys.stdin.read(1)
            print "Got character", repr(c)
        except IOError: pass
finally:
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

これを機能させるには、 termios モジュールと fcntl モジュールが必要です。他の場所でも機能するはずですが、Linuxでのみ試しました。 このコードでは、文字は一度に1つずつ読み取られて印刷されます。

termios.tcsetattr()は、stdinのエコーをオフにし、正規モードを無効にします。 fcntl.fnctl()は、stdinのファイル記述子フラグを取得し、それらを非ブロッキングモード用に変更するために使用されます。 空のときにstdinを読み取ると、IOErrorになるため、このエラーはキャッチされ、無視されます。


スレッド

スレッドを使用してプログラムするにはどうすればよいですか?

thread モジュールではなく、必ず threading モジュールを使用してください。 threading モジュールは、 thread モジュールによって提供される低レベルのプリミティブの上に便利な抽象化を構築します。

Aahzには、彼のスレッドチュートリアルからの役立つスライドのセットがあります。 http://www.pythoncraft.com/OSCON2001/を参照してください。


私のスレッドはどれも実行されていないようです:なぜですか?

メインスレッドが終了するとすぐに、すべてのスレッドが強制終了されます。 メインスレッドの実行速度が速すぎて、スレッドが作業を行う時間がありません。

簡単な修正は、すべてのスレッドが終了するのに十分な長さのスリープをプログラムの最後に追加することです。

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) # <----------------------------!

しかし、現在(多くのプラットフォームで)スレッドは並行して実行されていませんが、一度に1つずつ順番に実行されているように見えます! その理由は、前のスレッドがブロックされるまで、OSスレッドスケジューラが新しいスレッドを開始しないためです。

簡単な修正は、実行関数の開始に小さなスリープを追加することです。

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()の適切な遅延値を推測する代わりに、ある種のセマフォメカニズムを使用することをお勧めします。 1つのアイデアは、 Queue モジュールを使用してキューオブジェクトを作成し、各スレッドが終了時にキューにトークンを追加し、メインスレッドがスレッドと同じ数のトークンをキューから読み取るようにすることです。


多数のワーカースレッド間で作業を分割するにはどうすればよいですか?

Queue モジュールを使用して、ジョブのリストを含むキューを作成します。 Queue クラスはオブジェクトのリストを維持し、キューにアイテムを追加する.put(obj)メソッドと、それらを返す.get()メソッドを備えています。 クラスは、各ジョブが1回だけ配布されるようにするために必要なロックを処理します。

簡単な例を次に示します。

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(),
            print 'queue empty'
            break
        else:
            print 'Worker', threading.currentThread(),
            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)> running with argument 0
Worker <Thread(worker 2, started)> running with argument 1
Worker <Thread(worker 3, started)> running with argument 2
Worker <Thread(worker 4, started)> running with argument 3
Worker <Thread(worker 5, started)> running with argument 4
Worker <Thread(worker 1, started)> running with argument 5
...

詳細については、モジュールのドキュメントを参照してください。 Queue クラスは機能的なインターフェースを提供します。


どのような種類のグローバル値の変更がスレッドセーフですか?

グローバルインタープリターロック(GIL)は、PythonVMで一度に1つのスレッドのみが実行されるようにするために内部的に使用されます。 一般に、Pythonはバイトコード命令間でのみスレッドを切り替えることを提案します。 sys.setcheckinterval()を介して切り替える頻度を設定できます。 したがって、各バイトコード命令、したがって各命令から到達するすべてのC実装コードは、Pythonプログラムの観点からはアトミックです。

理論的には、これは正確なアカウンティングにはPVMバイトコードの実装を正確に理解する必要があることを意味します。 実際には、「アトミックに見える」組み込みデータ型(int、list、dictなど)の共有変数に対する操作が実際に行われることを意味します。

たとえば、次の操作はすべてアトミックです(L、L1、L2はリスト、D、D1、D2はdict、x、yはオブジェクト、i、jはint):

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

他のオブジェクトを置き換える操作は、参照カウントがゼロに達したときにそれらの他のオブジェクトの__del__()メソッドを呼び出す可能性があり、それが物事に影響を与える可能性があります。 これは、辞書とリストの一括更新に特に当てはまります。 疑わしい場合は、ミューテックスを使用してください。


グローバルインタプリタロックを取り除くことはできませんか?

グローバルインタープリターロック(GIL)は、ハイエンドマルチプロセッサーサーバーマシンでのPythonの展開の妨げと見なされることがよくあります。 )すべてのPythonコードは、GILが保持されている間のみ実行できます。

Python 1.5の時代に、Greg Steinは実際に包括的なパッチセット(「フリースレッド」パッチ)を実装し、GILを削除して、きめ細かいロックに置き換えました。 残念ながら、Windows(ロックが非常に効率的である)でも、これはGILを使用するインタープリターの約2倍の速度で通常のPythonコードを実行しました。 Linuxでは、pthreadロックがそれほど効率的ではないため、パフォーマンスの低下はさらに悪化しました。

それ以来、GILを取り除くというアイデアがときどき出てきましたが、予想される速度低下に対処する方法は誰も見つかりませんでした。スレッドを使用しないユーザーは、コードが半分の速度で実行された場合、満足できません。 Gregの無料のスレッドパッチセットは、それ以降のPythonバージョンでは最新の状態に保たれていません。

これは、マルチCPUマシンでPythonをうまく利用できないという意味ではありません。 複数のスレッドではなく、複数のプロセスに作業を分割することで創造性を発揮する必要があります。 C拡張機能の賢明な使用も役立ちます。 C拡張機能を使用して時間のかかるタスクを実行する場合、実行スレッドがCコード内にある間に拡張機能がGILを解放し、他のスレッドが作業を実行できるようにします。

GILは、真にグローバルではなく、インタプリタ状態ごとのロックである必要があることが示唆されています。 その場合、インタプリタはオブジェクトを共有できなくなります。 残念ながら、これも起こりそうにありません。 現在、多くのオブジェクト実装にはグローバル状態があるため、これは膨大な量の作業になります。 たとえば、小さい整数と短い文字列がキャッシュされます。 これらのキャッシュは、インタープリター状態に移行する必要があります。 他のオブジェクトタイプには、独自のフリーリストがあります。 これらの無料リストは、インタプリタ状態に移行する必要があります。 等々。

また、サードパーティの拡張機能にも同じ問題が存在するため、有限の時間でさえ実行できるとは思えません。 サードパーティの拡張機能は、すべてのグローバル状態をインタプリタ状態に格納するように変換するよりも速い速度で書き込まれている可能性があります。

そして最後に、状態を共有していない複数のインタープリターができたら、各インタープリターを別々のプロセスで実行することで何が得られましたか?


入出力

ファイルを削除するにはどうすればよいですか? (およびその他のファイルの質問…)

os.remove(filename)またはos.unlink(filename)を使用します。 ドキュメントについては、 os モジュールを参照してください。 2つの機能は同じです。 unlink()は、この関数のUnixシステムコールの名前です。

ディレクトリを削除するには、 os.rmdir()を使用します。 os.mkdir()を使用して作成します。 os.makedirs(path)は、pathに存在しない中間ディレクトリを作成します。 os.removedirs(path)は、中間ディレクトリが空である限り、それらを削除します。 ディレクトリツリー全体とその内容を削除する場合は、 shutil.rmtree()を使用してください。

ファイルの名前を変更するには、os.rename(old_path, new_path)を使用します。

ファイルを切り捨てるには、f = open(filename, "r+")を使用してファイルを開き、f.truncate(offset)を使用します。 オフセットのデフォルトは現在のシーク位置です。 os.open()で開かれたファイル用のos.ftruncate(fd, offset)もあります。ここで、 fd はファイル記述子(小さな整数)です。

shutil モジュールには、 copyfile()copytree()rmtree()などのファイルを操作するための関数も多数含まれています。 。


ファイルをコピーするにはどうすればよいですか?

shutil モジュールには、 copyfile()関数が含まれています。 MacOS 9では、リソースフォークとFinder情報はコピーされないことに注意してください。


バイナリデータを読み取る(または書き込む)にはどうすればよいですか?

複雑なバイナリデータ形式を読み書きするには、 struct モジュールを使用するのが最適です。 これにより、バイナリデータ(通常は数値)を含む文字列を取得して、Pythonオブジェクトに変換できます。 およびその逆。

たとえば、次のコードは、ファイルから2つの2バイト整数と1つの4バイト整数をビッグエンディアン形式で読み取ります。

import struct

f = open(filename, "rb")  # Open in binary mode for portability
s = f.read(8)
x, y, z = struct.unpack(">hhl", s)

フォーマット文字列の「>」は、ビッグエンディアンデータを強制します。 文字「h」は文字列から1つの「短整数」(2バイト)を読み取り、「l」は文字列から1つの「長整数」(4バイト)を読み取ります。

より規則的なデータの場合(例: intまたはfloatの同種リスト)、 array モジュールを使用することもできます。


os.popen()で作成されたパイプでos.read()を使用できないようです。 どうして?

os.read()は、開いているファイルを表す小さな整数であるファイル記述子を受け取る低レベルの関数です。 os.popen()は、組み込みの open()関数によって返されるのと同じタイプの高レベルのファイルオブジェクトを作成します。 したがって、 os.popen()で作成されたパイプ p から n バイトを読み取るには、p.read(n)を使用する必要があります。


入力と出力の両方に接続されたパイプでサブプロセスを実行するにはどうすればよいですか?

popen2 モジュールを使用します。 例えば:

import popen2
fromchild, tochild = popen2.popen2("command")
tochild.write("input\n")
tochild.flush()
output = fromchild.readline()

警告:一般に、これを行うのは賢明ではありません。子があなたからの入力を待っている間、プロセスが子からの出力を待ってブロックされるというデッドロックを簡単に引き起こす可能性があるからです。 これは、親が子が出力するよりも多くのテキストを出力することを期待していること、またはフラッシュがないためにデータがstdioバッファーにスタックしていることが原因である可能性があります。 もちろん、Pythonの親は、出力を読み取る前に子に送信するデータを明示的にフラッシュできますが、子がナイーブなCプログラムの場合、フラッシュ以降、インタラクティブであっても、出力を明示的にフラッシュしないように記述されている可能性があります。通常は自動です。

popen3()を使用してstdoutとstderrを読み取る場合にも、デッドロックが発生する可能性があることに注意してください。 2つのうちの1つが内部バッファーに対して大きすぎて(バッファーサイズを増やしても効果がない)、もう1つを最初にread()すると、デッドロックも発生します。

popen2のバグに関する注意:プログラムがwait()またはwaitpid()を呼び出さない限り、終了した子プロセスは削除されず、子プロセスの数に制限があるため、最終的にpopen2の呼び出しは失敗します。 os.WNOHANG オプションを指定して os.waitpid()を呼び出すと、これを防ぐことができます。 このような呼び出しを挿入するのに適した場所は、popen2を再度呼び出す前です。

多くの場合、本当に必要なのは、コマンドを介してデータを実行し、結果を取得することだけです。 データの量が非常に多い場合を除いて、これを行う最も簡単な方法は、データを一時ファイルに書き込み、その一時ファイルを入力としてコマンドを実行することです。 標準モジュール tempfile は、 mktemp()関数をエクスポートして、一意の一時ファイル名を生成します。

import tempfile
import os

class Popen3:
    """
    This is a deadlock-safe version of popen that returns
    an object with errorlevel, out (a string) and err (a string).
    (capturestderr may not work under windows.)
    Example: print Popen3('grep spam','\n\nhere spam\n\n').out
    """
    def __init__(self,command,input=None,capturestderr=None):
        outfile=tempfile.mktemp()
        command="( %s ) > %s" % (command,outfile)
        if input:
            infile=tempfile.mktemp()
            open(infile,"w").write(input)
            command=command+" <"+infile
        if capturestderr:
            errfile=tempfile.mktemp()
            command=command+" 2>"+errfile
        self.errorlevel=os.system(command) >> 8
        self.out=open(outfile,"r").read()
        os.remove(outfile)
        if input:
            os.remove(infile)
        if capturestderr:
            self.err=open(errfile,"r").read()
            os.remove(errfile)

多くのインタラクティブプログラム(例: vi)標準の入力と出力の代わりにパイプを使用するとうまく機能しません。 パイプの代わりに疑似tty(「ptys」)を使用する必要があります。 または、Pythonインターフェースを使用してDonLibesの「expect」ライブラリに接続することもできます。 インターフェースが期待するPython拡張機能は「expy」と呼ばれ、 http://expectpy.sourceforge.net から入手できます。 期待どおりに機能する純粋なPythonソリューションは、 pexpect です。


シリアル(RS232)ポートにアクセスするにはどうすればよいですか?

Win32、POSIX(Linux、BSDなど)の場合、Jython:

Unixについては、MitchChapmanによるUsenetの投稿を参照してください。

sys.stdout(stdin、stderr)を閉じないのはなぜですか?

Pythonファイルオブジェクトは、Cストリームの上にある高レベルの抽象化レイヤーであり、Cストリームは、(とりわけ)低レベルのCファイル記述子の上にある中レベルの抽象化レイヤーです。

組み込みのfileコンストラクターを介してPythonで作成するほとんどのファイルオブジェクトの場合、f.close()はPythonファイルオブジェクトをPythonの観点から閉じているものとしてマークし、基になるCストリームを閉じるように調整します。 。 これは、fがガベージになると、fのデストラクタでも自動的に発生します。

ただし、stdin、stdout、およびstderrは、Cによっても特別なステータスが与えられるため、Pythonによって特別に扱われます。 sys.stdout.close()を実行すると、Pythonレベルのファイルオブジェクトが閉じているとマークされますが、関連するCストリームはではなく閉じられます。

これら3つのうちの1つの基になるCストリームを閉じるには、最初にそれが本当に実行したいことであることを確認する必要があります(たとえば、I / Oを実行しようとしている拡張モジュールを混乱させる可能性があります)。 そうである場合は、os.closeを使用します。

os.close(0)   # close C's stdin stream
os.close(1)   # close C's stdout stream
os.close(2)   # close C's stderr stream

ネットワーク/インターネットプログラミング

Python用のWWWツールは何ですか?

ライブラリリファレンスマニュアルのインターネットプロトコルとサポートおよびインターネットデータ処理というタイトルの章を参照してください。 Pythonには、サーバー側とクライアント側のWebシステムの構築に役立つ多くのモジュールがあります。

利用可能なフレームワークの概要は、Paul Boddieによって https://wiki.python.org/moin/WebProgrammingで管理されています。

Cameron Lairdは、PythonWebテクノロジーに関する便利なページセットを http://phaseit.net/claird/comp.lang.python/web_python で管理しています。


CGIフォーム送信(METHOD = POST)を模倣するにはどうすればよいですか?

フォームをPOSTした結果のWebページを取得したいと思います。 これを簡単に行える既存のコードはありますか?

はい。 httplibを使用する簡単な例を次に示します。

#!/usr/local/bin/python

import httplib, sys, time

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

# connect and send the server a path
httpobj = httplib.HTTP('www.some-server.out-there', 80)
httpobj.putrequest('POST', '/cgi-bin/some-cgi-script')
# now generate the rest of the HTTP headers...
httpobj.putheader('Accept', '*/*')
httpobj.putheader('Connection', 'Keep-Alive')
httpobj.putheader('Content-type', 'application/x-www-form-urlencoded')
httpobj.putheader('Content-length', '%d' % len(qs))
httpobj.endheaders()
httpobj.send(qs)
# find out what the server said in response...
reply, msg, hdrs = httpobj.getreply()
if reply != 200:
    sys.stdout.write(httpobj.getfile().read())

一般に、パーセントエンコードされたPOST操作の場合、クエリ文字列は urllib.urlencode()を使用して引用符で囲む必要があることに注意してください。 たとえば、name=Guy Steele, Jr.を送信するには:

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

HTMLの生成を支援するためにどのモジュールを使用する必要がありますか?

役立つリンクのコレクションは、 Webプログラミングwikiページにあります。


Pythonスクリプトからメールを送信するにはどうすればよいですか?

標準ライブラリモジュール smtplib を使用します。

これは、それを使用する非常に単純なインタラクティブメール送信者です。 このメソッドは、SMTPリスナーをサポートするすべてのホストで機能します。

import sys, smtplib

fromaddr = raw_input("From: ")
toaddrs  = raw_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: [email protected]\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()メソッドでブロッキングを回避するにはどうすればよいですか?

selectモジュールは、ソケットでの非同期I / Oを支援するために一般的に使用されます。

TCP接続がブロックされないようにするには、ソケットを非ブロックモードに設定します。 次に、connect()を実行すると、すぐに接続するか(可能性は低い)、エラー番号を.errnoとして含む例外が発生します。 errno.EINPROGRESSは、接続が進行中であるが、まだ終了していないことを示します。 OSが異なれば、返される値も異なるため、システムに何が返されるかを確認する必要があります。

connect_ex()メソッドを使用して、例外の作成を回避できます。 errno値を返すだけです。 ポーリングするには、後でもう一度connect_ex()を呼び出すことができます–0またはerrno.EISCONNは接続していることを示します–または、このソケットを渡して、書き込み可能かどうかを確認するために選択できます。


データベース

Pythonのデータベースパッケージへのインターフェイスはありますか?

はい。

Python 2.3には、BerkeleyDBライブラリへのインターフェイスを提供する bsddb パッケージが含まれています。 DBMGDBM などのディスクベースのハッシュへのインターフェースも標準のPythonに含まれています。

ほとんどのリレーショナルデータベースのサポートが利用可能です。 詳細については、 DatabaseProgrammingwikiページを参照してください。


Pythonで永続オブジェクトをどのように実装しますか?

pickle ライブラリモジュールはこれを非常に一般的な方法で解決し(開いているファイル、ソケット、ウィンドウなどはまだ保存できません)、 shelve ライブラリモジュールはpickleと( g)dbmは、任意のPythonオブジェクトを含む永続的なマッピングを作成します。 パフォーマンスを向上させるには、 cPickle モジュールを使用できます。

物事を行うためのより厄介な方法は、ピクルスの妹、マーシャルを使用することです。 marshal モジュールは、非循環の基本的なPython型をファイルや文字列に格納したり、元に戻したりするための非常に高速な方法を提供します。 マーシャルは、インスタンスの保存や共有参照の適切な処理などの凝ったことはしませんが、非常に高速に実行されます。 たとえば、0.5メガバイトのデータのロードには3分の1秒未満かかる場合があります。 これは、pickle / shelveでgdbmを使用するなど、より複雑で一般的なことを行うよりも優れていることがよくあります。


cPickleがとても遅いのはなぜですか?

デフォルトでは、 pickle は、下位互換性のために比較的古くて遅い形式を使用します。 ただし、より高速な他のプロトコルバージョンを指定できます。

largeString = 'z' * (100 * 1024)
myPickle = cPickle.dumps(largeString, protocol=1)

bsddb(またはanydbm)データベースを開いた状態でプログラムがクラッシュすると、プログラムが破損します。 どうして?

bsddbモジュール(およびbsddbを優先的に使用するためanydbmモジュール)を使用して書き込みアクセス用に開かれたデータベースは、データベースの.close()メソッドを使用して明示的に閉じる必要があります。 基盤となるライブラリは、ディスク上の形式に変換して書き込む必要のあるデータベースの内容をキャッシュします。

新しいbsddbデータベースを初期化したが、プログラムがクラッシュする前に何も書き込まなかった場合、長さがゼロのファイルになってしまい、次にファイルを開いたときに例外が発生することがよくあります。


Berkeley DBファイルを開こうとしましたが、bsddbによってbsddb.error:(22、 '無効な引数')が生成されます。 ヘルプ! データを復元するにはどうすればよいですか?

慌てる必要はありません! あなたのデータはおそらく無傷です。 エラーの最も頻繁な原因は、以前のBerkeleyDBファイルを新しいバージョンのBerkeleyDBライブラリで開こうとしたことです。

多くのLinuxシステムでは、3つのバージョンすべてのBerkeleyDBを利用できるようになりました。 バージョン1から新しいバージョンに移行する場合は、db_dump185を使用してデータベースのプレーンテキストバージョンをダンプします。 バージョン2からバージョン3に移行する場合は、db2_dumpを使用してデータベースのプレーンテキストバージョンを作成します。 いずれの場合も、db_loadを使用して、コンピューターにインストールされている最新バージョンの新しいネイティブデータベースを作成します。 Berkeley DBのバージョン3がインストールされている場合は、db2_loadを使用してネイティブバージョン2データベースを作成できるはずです。

ハッシュファイルコードにはデータを破損する可能性のある既知のバグが含まれているため、BerkeleyDBバージョン1ファイルから離れる必要があります。


数学と数値

Pythonで乱数を生成するにはどうすればよいですか?

標準モジュール random は、乱数ジェネレーターを実装します。 使い方は簡単です:

import random
random.random()

これにより、[0、1)の範囲のランダムな浮動小数点数が返されます。

このモジュールには、次のような他の多くの特殊なジェネレーターもあります。

  • randrange(a, b)は、[a、b)の範囲の整数を選択します。
  • uniform(a, b)は、[a、b)の範囲の浮動小数点数を選択します。
  • normalvariate(mean, sdev)は、正規(ガウス)分布をサンプリングします。

次のような一部の高レベル関数は、シーケンスを直接操作します。

  • choice(S)は指定されたシーケンスからランダムな要素を選択します
  • shuffle(L)は、リストをインプレースでシャッフルします。 ランダムに並べ替えます

Randomクラスもあり、インスタンス化して独立した複数の乱数ジェネレーターを作成できます。