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

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

ただいまの
回答率

88.78%

Windowsでsignalと同様の処理を行いたい

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 696

groggy_egg

score 10

windowsでKNPを使おうと思い以下手順を実行しました
参考サイト

  • Juman++をインストール
  • KNPをインストール
  • pyknpをインストール
    →エラー :こちらを元にsetup.py修正
  • コマンドプロンプトで出力確認(juman,knp)
  • pythonでpyknp実行 
    テストコード①を実行した結果エラー

.../AppData\Local\Programs\Python\Python38\lib\site-packages\pyknp-0.4.1-py3.8.egg\pyknp\juman\juman.py", line 73, in juman_lines

.../AppData\Local\Programs\Python\Python38\lib\site-packages\pyknp-0.4.1-py3.8.egg\pyknp\juman\process.py", line 70, in query

AttributeError: module 'signal' has no attribute 'SIGALRM'

上記エラーを調べた結果→ 過去質問
windowsではsignalが使えないため書き換える必要があるそうです

エラー箇所

    def query(self, sentence, pattern):
        assert(isinstance(sentence, six.text_type))
        def alarm_handler(signum, frame):
            raise subprocess.TimeoutExpired(self.process_command, self.process_timeout)
        signal.signal(signal.SIGALRM, alarm_handler)
        signal.alarm(self.process_timeout)
        result = ""
        try:
            self.process.stdin.write(sentence.encode('utf-8')+six.b('\n'))
            self.process.stdin.flush()
            while True:
                line = self.process.stdout.readline().rstrip().decode('utf-8')
                if re.search(pattern, line):
                    break
                result = "%s%s\n" % (result, line)
        finally:
            signal.alarm(0)
        return result


上記の signal.alarm(...) は time.sleep(...) にすればいいと思ったのですが
signal.signal(... , ...) はどのように書き換えればいいのでしょうか?
(特にsignal.SIGALRMの箇所)

こちらを読んでみたのですがいまいちわかりませんでした。

詳しい方ご教授願います

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • t_obara

    2020/02/13 15:22

    提示したリンク(過去質問)には回答案が提示されています。こちらで試してみてはいかがでしょうか?
    ちなみに、SIGALRMの動作はご理解されているのですよね?

    キャンセル

  • groggy_egg

    2020/02/13 15:36

    SIGALRM以外の部分はなんとなくわかるのですが
    SIGALRMの部分をどう書き換えればいいのかがわかっていないです

    キャンセル

回答 3

check解決した方法

0

参考サイトを参考に自己解決?しました
(別件でエラーは出ましたがこのエラーは消えました)

        #signal.signal(signal.SIGALRM, alarm_handler)
        #signal.alarm(self.process_timeout)
        alarm = threading.Timer(self.process_timeout, alarm_handler)
        alarm.start()

              :
        #signal.alarm(0)
        alarm.cancel()

皆さん、回答&アドバイスありがとうございました

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

CTL + C のようなシグナル処理を受け付けるには
下記URLが参考になるかと思います。シグナル処理の話でなければご容赦下さい。
ここ

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/13 12:51

    シグナル処理の話ではありますが、Windowsではサポートされない、指定時間後に発生するSIGALRMシグナルのハンドリングの話だと思います。

    キャンセル

  • 2020/02/13 13:04

    すみません。単純にCTL+Cで割り込みをさせた時の話と誤解をしてました。

    キャンセル

0

まったく同じ処理は実現できないと思います。

基礎知識
シグナルというのは、「システム」や「プロセス」がプロセスに送ります。送られたプロセスは何をやっていたとしてもそのシグナルを受け取って、関連付けられたハンドラの処理を実行するようになっています。無視したければ、何もしないハンドラを関連付けます。

SIGALRMというシグナルは、タイムアウトとともに設定すると、「システム」がタイムアウト時間後にシグナルを送ってくれます。
システムがWindowsの場合、対応していないので、SIGALRMは送れません。

ソースをシグナル処理に着目した動作は
・呼ばれると例外を発生する関数を定義
・SIGALRMのハンドラにその関数を設定(signal.alarm())
・SIGALRMの設定 (signal.signal())
設定した時間後にSIGALRMが送られるようになる。
・例外を捕捉するようにする(try-catch)
・時間のかかるかもしれない/終わらないかもしれない処理を実施  ★
のようになっています。
そして、この「時間のかかるかもしれない処理」を実施しているときに、

  • 時間内に終われば、finallyでアラームを止めて、処理終了
  • タイムアウトすれば、例外が発生するので、処理が中断される。
    ということで、或る時間内にこの処理を終らせることができます。

アラームによるタイムアウトを使わない場合、ループを回して定期的に確認するなどして待ち合わせるのが一般的ですが、(★)の処理が「ブロックする」(=応答あるまで関数が帰ってこないなど)場合、その手が使えません。

何とかしたいということであれば、windowsでも他のシグナルは使えるようなので、別プロセスを立ち上げて、そこで時間を計って適切なタイミングで、シグナルを投げるなどでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/13 21:46

    回答ありがとうございます
    自分でも調べているのですが、ご説明のおかげで意味が理解できるようになりました。

    キャンセル

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

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る