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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Mecab

Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

VPS

VPS(バーチャル・プライベート・サーバ)は、仮想化されたサーバをレンタルするサービスで、共有サーバでありながら専門サーバと同等の機能を果たします。物理的な専門サーバより安価で提供できるメリットがあります。

Q&A

解決済

1回答

6546閲覧

コアダンプの原因と対策:VPS上での文章自動生成

bunks

総合スコア30

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Mecab

Mecabは、オープンソースの形態素解析エンジンです。 言語、辞書、コーパスに依存しない汎用的な設計を基本方針としています。 Mecabの由来は、開発者の好物である和布蕪(めかぶ)から名づけられました。

VPS

VPS(バーチャル・プライベート・サーバ)は、仮想化されたサーバをレンタルするサービスで、共有サーバでありながら専門サーバと同等の機能を果たします。物理的な専門サーバより安価で提供できるメリットがあります。

0グッド

0クリップ

投稿2018/10/09 10:35

編集2018/10/09 11:04

こちら(https://github.com/o-tomox/TextGenerator)のプログラムを基礎として,VPS上で文章を自動生成するツールを作っていますが,いざ自動生成プログラムに差し掛かると

・VPS上gunicorn --bindなら502 Bad Gateway
・VPS上manage.py runserver ならSegmentation fault (コアダンプ)

となって停止してしまいます。

同じプログラムでも,ローカルでは実行時間1秒ほどで問題なく動くのですが,VPSではうまく行きません。

nginxのエラーログを見たところ

upstream prematurely closed connection while reading response header from upstream

のようにでるのですが,例えばバックグラウンドのアプリが重いことなど,考えられる原因と対策を教えていただきたいです。

環境は以下の通りです。
・VPS(CentOS7)
・ローカル(MacOS)
・Django
・MeCab

views.py

def search(request): if request.method == 'GET': query = request.GET.get('your_name').encode('utf-8') s = Scraper(query) sample = s[0] urls = s[1] samples = s[2] chain = PrepareChain(sample) triplet_freqs = chain.make_triplet_freqs() chain.save(triplet_freqs, True) numb_sentence = int('3') #文章の数 generator = GenerateText() gen_txt = generator.generate() data = { 'your_name': gen_txt, 'urls': urls, 'samples': samples, } return render(request, 'app/home.html', data)

models.py

from django.db import models import sqlite3 import sys #PrepareChain import unittest import re import MeCab from collections import defaultdict #GenerateText import os.path import random #Scraper from bs4 import BeautifulSoup import urllib3 import requests import chardet from urllib.parse import parse_qsl from urllib.parse import urlparse from google import google import ssl ssl._create_default_https_context = ssl._create_unverified_context class Text(models.Model): query_text = models.CharField(max_length = 5000) def __str__(self): return self.query_text class Query(models.Model): query_text = models.CharField(max_length = 40) def __str__(self): return self.query_text def Scraper(x): #setup urls = [] samples = [] query = x query = query.decode('utf-8') num_page = 1 search_results = google.search(query, num_page) for result in search_results: urls.append(result.link) samples.append(result.description) print(samples) sample = ''.join(samples) #Generating txt file return [sample, urls, samples] class PrepareChain(object): """ チェーンを作成してDBに保存するクラス """ BEGIN = "__BEGIN_SENTENCE__" END = "__END_SENTENCE__" DB_PATH = "chain.db" DB_SCHEMA_PATH = "schema.sql" def __init__(self, text): """ 初期化メソッド @param text チェーンを生成するための文章 """ if isinstance(text, bytes): text = text.decode('utf-8') self.text = text # 形態素解析用タガー self.tagger = MeCab.Tagger('-Ochasen') def make_triplet_freqs(self): """ 形態素解析から3つ組の出現回数まで @return 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ sentences = self._divide(self.text) # 3つ組の出現回数 triplet_freqs = defaultdict(int) # センテンス毎に3つ組にする for sentence in sentences: # 形態素解析 morphemes = self._morphological_analysis(sentence) # 3つ組をつくる triplets = self._make_triplet(morphemes) # 出現回数を加算 for (triplet, n) in list(triplets.items()): triplet_freqs[triplet] += n return triplet_freqs def _divide(self, text): """ 「。」や改行などで区切られた長い文章を一文ずつに分ける @param text 分割前の文章 @return 一文ずつの配列 """ # 改行文字以外の分割文字(正規表現表記) delimiter = "。|.|." # 全ての分割文字を改行文字に置換(splitしたときに「。」などの情報を無くさないため) text = re.sub(r"({0})".format(delimiter), r"\1\n", text) # 改行文字で分割 sentences = text.splitlines() # 前後の空白文字を削除 sentences = [sentence.strip() for sentence in sentences] return sentences def _morphological_analysis(self, sentence): """ 一文を形態素解析する @param sentence 一文 @return 形態素で分割された配列 """ morphemes = [] node = self.tagger.parseToNode(sentence) while node: if node.posid != 0: morpheme = node.surface morphemes.append(morpheme) node = node.next return morphemes def _make_triplet(self, morphemes): """ 形態素解析で分割された配列を、形態素毎に3つ組にしてその出現回数を数える @param morphemes 形態素配列 @return 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ # 3つ組をつくれない場合は終える if len(morphemes) < 3: return {} # 出現回数の辞書 triplet_freqs = defaultdict(int) # 繰り返し for i in range(len(morphemes)-2): triplet = tuple(morphemes[i:i+3]) triplet_freqs[triplet] += 1 # beginを追加 triplet = (PrepareChain.BEGIN, morphemes[0], morphemes[1]) triplet_freqs[triplet] = 1 # endを追加 triplet = (morphemes[-2], morphemes[-1], PrepareChain.END) triplet_freqs[triplet] = 1 return triplet_freqs def save(self, triplet_freqs, init=False): """ 3つ組毎に出現回数をDBに保存 @param triplet_freqs 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ # DBオープン con = sqlite3.connect(PrepareChain.DB_PATH) # 初期化から始める場合 if init: # DBの初期化 with open(PrepareChain.DB_SCHEMA_PATH, "r") as f: schema = f.read() con.executescript(schema) # データ整形 datas = [(triplet[0], triplet[1], triplet[2], freq) for (triplet, freq) in triplet_freqs.items()] # データ挿入 p_statement = "insert into chain_freqs (prefix1, prefix2, suffix, freq) values (?, ?, ?, ?)" con.executemany(p_statement, datas) # コミットしてクローズ con.commit() con.close() def show(self, triplet_freqs): """ 3つ組毎の出現回数を出力する @param triplet_freqs 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ for triplet in triplet_freqs: print("|".join(triplet), "\t", triplet_freqs[triplet]) class GenerateText(object): """ 文章生成用クラス """ def __init__(self, n=5): """ 初期化メソッド @param n いくつの文章を生成するか """ self.n = n def generate(self): """ 実際に生成する @return 生成された文章 """ # DBが存在しないときは例外をあげる if not os.path.exists(PrepareChain.DB_PATH): raise IOError("DBファイルが存在しません") # DBオープン con = sqlite3.connect(PrepareChain.DB_PATH) con.row_factory = sqlite3.Row # 最終的にできる文章 generated_text = "" # 指定の数だけ作成する for i in range(self.n): text = self._generate_sentence(con) generated_text += text # DBクローズ con.close() return generated_text def _generate_sentence(self, con): """ ランダムに一文を生成する @param con DBコネクション @return 生成された1つの文章 """ # 生成文章のリスト morphemes = [] # はじまりを取得 first_triplet = self._get_first_triplet(con) morphemes.append(first_triplet[1]) morphemes.append(first_triplet[2]) # 文章を紡いでいく while morphemes[-1] != PrepareChain.END: prefix1 = morphemes[-2] prefix2 = morphemes[-1] triplet = self._get_triplet(con, prefix1, prefix2) morphemes.append(triplet[2]) # 連結 result = "".join(morphemes[:-1]) return result def _get_chain_from_DB(self, con, prefixes): """ チェーンの情報をDBから取得する @param con DBコネクション @param prefixes チェーンを取得するprefixの条件 tupleかlist @return チェーンの情報の配列 """ # ベースとなるSQL sql = "select prefix1, prefix2, suffix, freq from chain_freqs where prefix1 = ?" # prefixが2つなら条件に加える if len(prefixes) == 2: sql += " and prefix2 = ?" # 結果 result = [] # DBから取得 cursor = con.execute(sql, prefixes) for row in cursor: result.append(dict(row)) return result def _get_first_triplet(self, con): """ 文章のはじまりの3つ組をランダムに取得する @param con DBコネクション @return 文章のはじまりの3つ組のタプル """ # BEGINをprefix1としてチェーンを取得 prefixes = (PrepareChain.BEGIN,) # チェーン情報を取得 chains = self._get_chain_from_DB(con, prefixes) # 取得したチェーンから、確率的に1つ選ぶ triplet = self._get_probable_triplet(chains) return (triplet["prefix1"], triplet["prefix2"], triplet["suffix"]) def _get_triplet(self, con, prefix1, prefix2): """ prefix1とprefix2からsuffixをランダムに取得する @param con DBコネクション @param prefix1 1つ目のprefix @param prefix2 2つ目のprefix @return 3つ組のタプル """ # BEGINをprefix1としてチェーンを取得 prefixes = (prefix1, prefix2) # チェーン情報を取得 chains = self._get_chain_from_DB(con, prefixes) # 取得したチェーンから、確率的に1つ選ぶ triplet = self._get_probable_triplet(chains) return (triplet["prefix1"], triplet["prefix2"], triplet["suffix"]) def _get_probable_triplet(self, chains): """ チェーンの配列の中から確率的に1つを返す @param chains チェーンの配列 @return 確率的に選んだ3つ組 """ # 確率配列 probability = [] # 確率に合うように、インデックスを入れる for (index, chain) in enumerate(chains): for j in range(chain["freq"]): probability.append(index) # ランダムに1つを選ぶ chain_index = random.choice(probability) return chains[chain_index]

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

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

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

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

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

mather

2018/10/09 10:45

あなたの書いたソースコードを提示してください。
bunks

2018/10/09 10:53

ビューの該当箇所と,モデルを記述しました。よろしくお願いします。
mather

2018/10/09 10:56

def search(request) の返り値はどうなってるんですか?
bunks

2018/10/09 11:04

書き漏れていましたすみません。 追記の通り,return render(request, 'app/home.html', data)です。
mather

2018/10/09 11:13

renderは from django.shortcuts import render で合ってますか?
bunks

2018/10/09 11:16

あっています。
guest

回答1

0

ベストアンサー

エラーを見る限り Python プロセスが途中で終了しています。
ただ、質問にはPythonのエラーログがないので、エラーログの参照と logging モジュールによるログを仕込んでデバッグするしかないと思います。

投稿2018/10/09 11:20

mather

総合スコア6753

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

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

bunks

2018/10/09 12:29

ログが出る前にSegmentation fault (core dumped)となって,エラーがわからない状態ですが,調べつつデバッグして行きます。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問