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

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

関連記事

Slackでコマンドを作る方法をご紹介(自作スラッシュコマンド)

  <目次> (1) Slackでコマンドを作る方法をご紹介(自作スラッシュコマンド)  (1-0) やりたいこと  (1-1) STEP1:Slackボットの開発(所要時間:60分)  ( …

CondaHTTPError: HTTP 000 CONNECTION FAILED for url XXXXエラーの対処方法

  <目次> (1) CondaHTTPError: HTTP 000 CONNECTION FAILED for url XXXXエラーの対処方法  (1-1) 事象概要とエラーメッセージ …

PythonでAPIを呼び出すサンプルプログラムをご紹介

  <目次> (1) PythonでAPIを呼び出すサンプルプログラム  (1-1) 構文  (1-2) STEP1:事前準備  (1-3) STEP2:疎通①(最もシンプルなAPI呼び出し …

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

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

PythonでAPI呼び出す時のヘッダー、ボディの指定方法について

  <目次> (1) PythonでAPI呼び出す時のヘッダー、ボディの指定方法について  (1-1) 記事の概要  (1-2) ①「ヘッダー」の指定方法  (1-3) ②「ボディ」の指定方 …

  • English (United States)
  • 日本語
Top