Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Python

Pythonのdatapackage学習中に遭遇したエラー「StopIteration」と「AttributeError」の対応

投稿日:2020年3月1日 更新日:

(0)目次&概説

(1) 記事の目的
(2) エラー1:AttributeError: ‘generator’ object has no attribute ‘next’
 (2-1) エラー概要
 (2-2) 原因
 (2-3) 対処法
(3) エラー2:StopIteration
 (3-1) エラー概要
 (3-2) 原因
 (3-3) 対処法

(1) 記事の目的

この記事ではdatapackageの学習中に直面したエラーとその解決策を備忘として記録します。
目次にもどる

(2) エラー1:AttributeError: ‘generator’ object has no attribute ‘next’

(2-1) エラー概要

このエラーはdatapackageのPackageクラスを使ってcsvデータをロードして、iter()メソッドを使ってイテレータ(リストと似てるが取り出すと空になる)を作り、次の要素を取り出そうとして「next()」メソッドを呼び出した時に発生しました。

(図211)

■エラーしたプログラム
(エラー発生行は16行目)

import datapackage

def count(iter):
    try:
        return len(iter)
    except TypeError:
        return sum(1 for _ in iter)

def main():

    url = 'https://raw.githubusercontent.com/frictionlessdata/example-data-packages/master/periodic-table/datapackage.json'
    dp = datapackage.Package(url)
    print([e['name'] for e in dp.resources[0].read(keyed=True) if int(e['atomic number']) < 10])

    rows = datapackage.Package(url).resources[0].iter()
    print(rows.next())

if __name__ == '__main__':
    main()

目次にもどる

(2-2) 原因

結論としては「next()」メソッドではなく「__next__()」メソッドが正しいです。今回の例ではイテレータ(Generatorクラス)に「next」属性が無い事がエラーメッセージから分かります。実際に関数の型を「type()」で調べると「<class ‘generator’>」となっており、

(図221)

Pythonのドキュメントの「ジェネレータ-イテレータメソッド」を見ると、Python3では「__next__()」である事が分かります(しかし「next()」はforループで回せないので用途は少ないかも)。

https://docs.python.org/ja/3/reference/expressions.html?highlight=generator#generator.__next__

目次にもどる

(2-3) 対処法

上記の通り「__next()__」を使うと正しく次の値を取得できました。

(図231)

■改善後のプログラム
(差分は16行目の「print(rows.next())」→「print(rows.__next__())」)

import datapackage

def count(iter):
    try:
        return len(iter)
    except TypeError:
        return sum(1 for _ in iter)

def main():

    url = 'https://raw.githubusercontent.com/frictionlessdata/example-data-packages/master/periodic-table/datapackage.json'
    dp = datapackage.Package(url)
    print([e['name'] for e in dp.resources[0].read(keyed=True) if int(e['atomic number']) < 10])

    rows = datapackage.Package(url).resources[0].iter()
    print(rows.__next__())

if __name__ == '__main__':
    main()

目次にもどる

(3) エラー2:StopIteration

(3-1) エラー概要

これはエラーと言うよりは単にIteratorに対する私の理解不足だっただけですが、イテレータの要素数をcountしてからループ処理で要素を取りだそうとしたら「StopIteration」のエラーが出ました。

(図311)

■エラーしたプログラム
(エラー発生行は18行目の「print(rows.__next__())」)

import datapackage

def count(iter):
    try:
        return len(iter)
    except TypeError:
        return sum(1 for _ in iter)

def main():

    url = 'https://raw.githubusercontent.com/frictionlessdata/example-data-packages/master/periodic-table/datapackage.json'
    dp = datapackage.Package(url)
    print([e['name'] for e in dp.resources[0].read(keyed=True) if int(e['atomic number']) < 10])

    rows = dp.resources[0].iter()
    print(count(rows))
    for i in range(2):
        print(rows.__next__())

if __name__ == '__main__':
    main()

 

目次にもどる

(3-2) 原因

原因はその直前のcount関数の内部でlen()関数を呼んでおり、そのタイミングでイテレータの末尾まで到達してしまったために、要素を取りだそうとした瞬間に次の要素は無く「StopIter」となってしまったと推定します。

目次にもどる

(3-3) 対処法

対処方法としてはcount関数を使わずに、次の構文でイテレータの内容を順番に取り出します。

for i in rows:
    print(i)

(図331)

■改善後のプログラム
(16~17行目のforループの書き方を修正)

import datapackage

def count(iter):
    try:
        return len(iter)
    except TypeError:
        return sum(1 for _ in iter)

def main():

    url = 'https://raw.githubusercontent.com/frictionlessdata/example-data-packages/master/periodic-table/datapackage.json'
    dp = datapackage.Package(url)
    print([e['name'] for e in dp.resources[0].read(keyed=True) if int(e['atomic number']) < 10])

    rows = dp.resources[0].iter()
    for i in rows:
        print(i)

if __name__ == '__main__':
    main()

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Python

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

no image

PythonでJSON形式データの値を取得する手順について

  <目次> (1) PythonでJSON形式データの値を取得する手順について  (1-1) サンプル①:ローカルのJSONファイルの読み込み(単純構造)  (1-2) サンプル②:ローカ …

PythonでAzure Blob Storageからcsvを取得する方法について

  <目次> (1) PythonでAzure Blob Storageからcsvを取得する方法について  (1-1) STEP1:Pythonの依存性解決  (1-2) STEP2:Azu …

PythonでPandasライブラリを用いてcsvファイルを読み込む方法

<目次> (1) PythonでPandasライブラリを用いてcsvファイルを読み込む方法  (1-1) 構文  (1-2) サンプルプログラム  (1-3) read_csvの主要なオプションご紹介 …

Pythonでargparseを用いて引数を受け取って実行する方法

<目次> (1) Pythonでargparseを用いて引数を受け取って実行する方法  (1-1) argparseとは?  (1-2) 基本的な使い方  (1-3) サンプルプログラム (2) 参考 …

PythonのTkinterでテキストボックスの値を取得する方法

<目次> (1) PythonのTkinterでテキストボックスの値を取得する方法  (1-1) 構文  (1-2) キャンバスの設定  (1-3) 入力ボックスの追加  (1-4) ボタン押下時の処 …

  • English (United States)
  • 日本語
Top