Pythonのqueue(キュー)モジュールでマルチスレッドを使用する


Pythonでキュー(queue)を扱う方法を知りたい
そもそもデータ構造って何?
Pythonでマルチスレッドを扱う方法が知りたい

皆さんはキューやスタックなどのデータ構造については知っていますか?今回はPythonでキューやスタックを扱う方法について解説していきます!

この記事では、

  • データ構造とは
  • キューとは
  • スタックとは
  • queueモジュールの使い方(FIFO、LIFO)
  • queueモジュールでマルチスレッドを扱う方法

などの基本的な内容から解説していきます。データ構造についてもこの記事で解説していくのでぜひご覧ください!

本記事を読む前に、Pythonがどんなプログラミング言語なのかをおさらいしておきたい人は次の記事を参考にしてください。

→ Pythonとは?特徴やできること、活用例をわかりやすく簡単に解説

なお、その他のPythonの記事についてはこちらにまとめています。

目次

Pythonのqueueモジュールとは

データ構造とは

キューについて知る前に、まずはデータ構造について知っておきましょう。データ構造は、データの集まりをコンピュータで効率よく扱う仕組みのことを言います。

ソフトウェアの開発ではどのデータ構造を適切な場面で使えるかによって使い勝手や性能が大きく変わってきます。そのデータ構造の一つに、キューやスタックと呼ばれるものがあります。

キューとは

キューは基本的なデータ構造の一つです。

コンビニやデパートなどでレジに並ぶときを思い出してみてください。先に並んだ人が先に会計をしてもらい、後から来た人はその人の後ろに続いて…と言う構造になってますよね。

この先入れ先出し、First In First Out(FIFO)の構造を、キューと呼びます。このキューにデータを入れていくと、入れた順番通りの順番に、データを取り出すことができて、途中のデータだけを取り出すという操作は出来ないことになっています。

またキューにデータを入れることをエンキュー、データを取り出すことをデキューと呼びます。

スタックとは

スタックについても触れておきましょう。スタックはキューとよく比較される対象のデータ構造になります。

机に積み重なった書類を思い出してみてください。最初の書類ほど下になり、新しい書類ほど上に積み重なっていきますよね。

この後入れ先出し、Last In First Out(LIFO)の構造をスタックと呼びます。このスタックにデータを入れていくと、入れた順番とは逆の順番に、データを取り出すことが出来ます。

またこのスタックも途中のデータだけを取り出すという操作は出来ません。このスタックにデータを入れることをプッシュ、データを取り出すことをポップと呼びます。

基本的にはスタックとキューは別の扱いになることが多いのですが、Pythonのqueueモジュールではそれぞれのクラスがまとめられています。

queueモジュールを使用するには

上記で解説したスタックとキューを自分で実装するのは意外と簡単なのですが、このqueueモジュールを使えばメソッドの呼び出しだけで更に簡単に使うことが出来ます。

queueモジュールを使用するには、まずimportしておく必要があります。

import queue

これでエラーが出なければimportは成功です。

もしPython2系を使っているのであれば、

import Queue

のように、大文字で指定してみてください。

Python2系と3系ではこのように大文字表記から小文字表示に変更されているので気をつけましょう。以降この記事ではPython3系について解説をしていきます。

queueモジュールの基本的な使い方

FIFOキュー(キュー)

それでは一般的なキューを使ってみましょう。

こちらのコードをご覧ください。

from queue import Queue

q = Queue()

abc = ['a','b','c','d','e']
for i in abc:
    q.put(i)
    print("Enqueue:"+i)

print("--------")

while True:
    if q.empty():
        break
    else:
        i = q.get()
        print("Dequeue:"+i)

実行結果

Enqueue:a
Enqueue:b
Enqueue:c
Enqueue:d
Enqueue:e
--------
Dequeue:a
Dequeue:b
Dequeue:c
Dequeue:d
Dequeue:e

まずはqueueモジュールからQueueクラスを選んでimportしています。

importの詳しい解説はこちらの記事をご覧ください。

はじめてのPython!パッケージをimportする方法をやさしく解説!
更新日:2024年3月1日

そしてabcというリストの中にある文字を一つずつエンキューしています。その後にqが空になるまで、qの中身をデキューしています。実行結果に並ぶ順番が同じなので、FIFOが確認出来ましたね。

LIFOキュー(スタック)

次はスタックを使ってみましょう。

こちらのコードをご覧ください。

from queue import LifoQueue

q = LifoQueue()

abc = ['a','b','c','d','e']
for i in abc:
    q.put(i)
    print("Enqueue:"+i)

print("--------")

while True:
    if q.empty():
        break
    else:
        i = q.get()
        print("Dequeue:"+i)

実行結果

Enqueue:a
Enqueue:b
Enqueue:c
Enqueue:d
Enqueue:e
--------
Dequeue:e
Dequeue:d
Dequeue:c
Dequeue:b
Dequeue:a

まずは先程のように、queueモジュールからLifoQueueクラスを選んでimportしています。そしてabcというリストの中にある文字を一つずつプッシュしています。その後にqが空になるまで、qの中身をポップしています。

実行結果に並ぶ順番がちょうど逆になっているので、LIFOが確認出来ましたね。

ちなみにputメソッドとgetメソッドはパブリックで用意されているので、キューとスタックでは共通で使うことが出来ます。

queueモジュールでマルチスレッドを扱う

ここまでは基本的なqueueモジュールの扱い方について見てきました。ここからは関連性のあるマルチスレッドプログラミングについて、簡単に学んでいきましょう。

PythonはC言語などに比べて比較的速度の遅いプログラミング言語ですが、処理速度を上げたいような重い処理がある場合は、マルチスレッドを扱った並行処理をする必要が出てきます。

基本的なプログラムはシングルスレッドで、上から下に向けて順番に、一つ一つ処理を終わらせていくのが基本です。ただ、マルチスレッドの場合は、ある処理を行いながら、もう一つの処理を同時に行うことで処理速度を上げることが出来ます。

それでは早速コードを見ていきましょう。

import threading, queue
import time

def printNum(num, q):
    for i in num:
        print("Num:",i)
        time.sleep(5)
        q.put(i)

def addX(q):
    while True:
        _num = q.get()
        _num += 10
        print("Num(add10):",_num);
        time.sleep(10)
        q.task_done()

q = queue.Queue()
for n in range(2):
    thread = threading.Thread(target=addX, args=(q,))
    thread.start()

num = [1,2,3,4,5,6,7,8,9]
printNum(num, q)
q.join()

このコードではthreadingとtimeというモジュールをimportしていますがここで必要なのはthreadingモジュールです。このthreadingモジュールでprintNum関数とaddX関数を並行処理させています。

また並行処理をさせるためにキューを使って、それぞれの関数で値を渡して<います。並行処理はプログラミングの中でも共通してやや難しい分野になっているので、ここではこのようなプログラミングの仕方もあるんだといった程度に覚えておきましょう。

まとめ

今回はqueueモジュールについて、キューとスタック<を解説してきました。基本的なデータ構造についてわかって頂けたでしょうか?

queueモジュールでは同じメソッドを違うクラスでも使うことが出来ます。

もしキューやスタックについて忘れてしまったときは、またぜひこの記事をご覧ください!

この記事を書いた人

侍エンジニア塾は「人生を変えるプログラミング学習」をコンセンプトに、過去多くのフリーランスエンジニアを輩出したプログラミングスクールです。侍テック編集部では技術系コンテンツを中心に有用な情報を発信していきます。

目次