質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

3414閲覧

Error closing cursorとCannot operate on a closed databaseを解決したいです。お願いします。

jury_new

総合スコア31

SQLite

SQLiteはリレーショナルデータベース管理システムの1つで、サーバーではなくライブラリとして使用されている。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/04/06 03:22

編集2020/04/07 03:54

前提・実現したいこと

データベースにリンクを格納する。そのため上記のエラーを解決したいです。

2018年に出版された本を元にコードを書いています。
recordsライブラリを使いsqliteのデータベースを管理、
そして乱数放送局をエミュレートしデータベースにランダムな番号の一覧と別のページへのリンクを格納しようとしています。

コードを全てミスがないか確認、理解して実行したのですがどうも思った様な結果が出ません。
実行後データベースを確認するとテーブルは作成されている様なのですが、そのテーブルの中にランダムな番号の一覧と別ページのリンクがありません。ターミナルよりエラーを確認した所この様なエラーが出ていたのでこれが原因でないかと推測しました。まだまだ勉強を始めたばかりでどうもわからないのですが、返答頂けるとありがたいです。

発生している問題・エラーメッセージ

Error closing cursor Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1324, in fetchone row = self._fetchone_impl() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1204, in _fetchone_impl return self.cursor.fetchone() sqlite3.ProgrammingError: Cannot operate on a closed database. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1339, in _safe_close_cursor cursor.close() sqlite3.ProgrammingError: Cannot operate on a closed database. Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1324, in fetchone row = self._fetchone_impl() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1204, in _fetchone_impl return self.cursor.fetchone() sqlite3.ProgrammingError: Cannot operate on a closed database. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "seven.py", line 113, in <module> url_to_visit = get_random_unvisited_page() File "seven.py", line 72, in get_random_unvisited_page link =db.query('''SELECT *FROM pages File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 214, in first record = self[0] File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 152, in __getitem__ next(self) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 136, in __next__ nextrow = next(self._rows) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/records.py", line 365, in <genexpr> row_gen = (Record(cursor.keys(), row) for row in cursor) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 999, in __iter__ row = self.fetchone() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1331, in fetchone self.connection._handle_dbapi_exception( File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1481, in _handle_dbapi_exception util.raise_( File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 178, in raise_ raise exception File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1324, in fetchone row = self._fetchone_impl() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 1204, in _fetchone_impl return self.cursor.fetchone() sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) Cannot operate on a closed database. (Background on this error at: http://sqlalche.me/e/f405)

該当のソースコード

python

1import requests 2import records 3import re 4import os,os.path 5from bs4 import BeautifulSoup 6from urllib.parse import urljoin, urldefrag 7from sqlalchemy.exc import IntegrityError 8 9db =records.Database('sqlite:///wikipedia.db') 10 11db.query('''CREATE TABLE IF NOT EXISTS pages( 12 url text PRIMARY KEY, 13 created_at datetime, 14 html_file text Null, 15 visited_at datetime Null)''') 16 17db.query('''CREATE TABLE IF NOT EXISTS links( 18 url text,link_url text, 19 PRIMARY KEY (url,link_url))''') 20 21db.query('''CREATE TABLE IF NOT EXISTS images( 22 url text,img_url text,img_file text, 23 PRIMARY KEY (url,img_url))''') 24 25base_url = 'https://en.wikipedia.org/wiki/' 26file_store = './downloads/' 27 28if not os.path.exists(file_store): 29 os.makedirs(file_store) 30 31def url_to_file_name(url): 32 url = str(url).strip().replace('','') 33 return re.sub(r'(?u)[^-\w.]','',url) 34 35def download(url,filename): 36 r =requests.get(url,stream=True) 37 with open(os.path.join(file_store,filename),'wb') as the_image: 38 for byte_chunk in r.iter_content(chunk_size=4096*4): 39 the_image.write(byte_chunk) 40 41def store_page(url): 42 try: 43 db.query('''INSERT INTO pages (url,created_at) 44 VALUES(:url,CURRENT_TIMESTAMP)''', 45 url=url) 46 except IntegrityError as ie: 47 pass 48def store_link(url,link_url): 49 try: 50 db.query('''INSERT INTO links(url,link_url) 51 VALUES(:url,:link_url)''', 52 url=url,link_url=link_url) 53 except InergrityError as ie: 54 pass 55 56def store_image(url,img_url,img_file): 57 try: 58 db.query('''INSERT INTO images(url,img_url,img_file) 59 VALUES(:url,:img_url,:img_file)''', 60 url=url, img_url=img_url,img_file=img_file) 61 except IntegrityError as ie: 62 pass 63 64def set_visited(url,html_file): 65 db.query('''UPDATE pages 66 SET visited_at=CURRENT_TIMESTAMP, 67 html_file=:html_file 68 WHERE url=:url''', 69 url=url,html_file=html_file) 70 71def get_random_unvisited_page(): 72 link =db.query('''SELECT * FROM pages 73 WHERE visited_at Is NULL 74 ORDER BY RANDOM() LIMIT 1''').first() 75 return None if link is None else link.url 76 77def should_visit(link_url): 78 link_url = urldefrag(link_url)[0] 79 if not link_url.startswith(base_url): 80 return None 81 return link_url 82 83def visit(url): 84 print('Now visiting:',url) 85 html = requests.get(url).text 86 html_soup = BeautifulSoup(html,'html.parser') 87 88 for link in html_soup.find_all("a"): 89 link_url =link.get('href') 90 if link_url is None: 91 continue 92 link_url = urljoin(base_url, link_url) 93 store_link(url,link_url) 94 full_url=should_visit(link_url) 95 if full_url: 96 store_page(full_url) 97 for img in html_soup.find_all("img"): 98 img_url = img.get('src') 99 if img_url is None: 100 continue 101 img_url = urljoin(base_url,img_url) 102 filename = url_to_file_name(img_url) 103 download(img_url,filename) 104 store_image(url,img_url,filename) 105 106 filename = url_to_file_name(url) + 'html' 107 fullname = os.path.join(file_store,filename) 108 with open(fullname,'w','encoding=utf-8') as the_html: 109 the_html.write(html) 110 set_visited(url,filename) 111 112store_page(base_url) 113url_to_visit = get_random_unvisited_page() 114while url_to_visit is not None: 115 visit(url_to_visit) 116 url_to_visit = get_random_unvisited_page() 117

試したこと

エラーの内容をググリました。直訳ではdatabase、cursorが閉じているとのこと。
コードは合っている?と思ったので直接エラーを調べました。
結果海外のサイトでrecordsのバージョンを0.52にすることで解決しましたと見つけました。
バージョンが変わってしまうとどうしようもないのでしょうか?または、他に問題があるのでしょうか?

補足情報(FW/ツールのバージョンなど)

**records 0.5.3 **

beautifulsoup4 4.8.2
certifi 2019.11.28
chardet 3.0.4
docopt 0.6.2
et-xmlfile 1.0.1
idna 2.9
jdcal 1.4.1
openpyxl 2.4.11
pip 20.0.2
requests 2.23.0
selenium 3.141.0
setuptools 41.2.0
soupsieve 2.0
SQLAlchemy 1.3.15
tablib 1.1.0
urllib3 1.25.8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2020/04/07 02:40

関係あるか知りませんが、get_random_unvisited_page の SELECT * の後ろが全角スペースになってます。
jury_new

2020/04/07 03:58

返答、ご指摘ありがとうございます。今のところエラーの改善はみられませんがもう一度確認していこうと思います。
jury_new

2020/04/07 06:27

そうでしたか、、違うライブラリを使用することを検討してみます。 ありがとうございました。
hoshi-takanori

2020/04/07 06:29

とりあえず動かしたいのであれば、以下のコマンドで修正版を入れる方法もあるようです。 pip install --upgrade 'git+https://github.com/shacknetisp/records.git@ee04fb246889b6bcf0d5ffbc9337c047da5eaa34'
jury_new

2020/04/07 06:43

ありがとうございます。重ねてもうひとつ宜しいでしょうか?本当に初歩的なことを聞いてしまうのですが、コマンドで修正版を手に入れると言うのはターミナルに上記3文を入力すると言うことでよかったでしょうか?何度も申し訳ありません。
hoshi-takanori

2020/04/07 06:46

あ、なんかコメント欄だとおかしくなりますね。回答欄に書き直します。
guest

回答1

0

ベストアンサー

records 0.5.3 にはバグがあって sqlite3 だとうまく動かないようです。
参考: https://github.com/kennethreitz-archive/records/issues/149

マージされてない修正版のプルリクがあるので、それを使うには次のコマンドを実行すればいいと思います。
(改行されて見えるかもしれませんが、一行のコマンドです。また、pip じゃなくて pip3 を使ってる場合は最初の pip を書き換えて実行してください。)

pip install --upgrade 'git+https://github.com/shacknetisp/records.git@ee04fb246889b6bcf0d5ffbc9337c047da5eaa34'

投稿2020/04/07 06:50

hoshi-takanori

総合スコア7895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jury_new

2020/04/07 06:57

ご丁寧にありがとうございます。とても分かりやすいです。 ずっと悩んでいたのですっきりしました。本当に助かりました。
jury_new

2020/04/07 07:00

上記のエラーは改善しました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問