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

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

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

VimとはUnix / Linux 系のOSに標準搭載されているターミナル上で動くテキストエディタです。

Python

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

Q&A

解決済

1回答

2685閲覧

vim-quickrunでjobを使うとPythonのsubprocessで標準出力を取得するプログラムが動かない

terai

総合スコア15

Vim

VimとはUnix / Linux 系のOSに標準搭載されているターミナル上で動くテキストエディタです。

Python

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

0グッド

0クリップ

投稿2020/05/04 06:59

編集2020/05/04 09:48

前提・実現したいこと

Vimプラグインのvim-quickrunを使って、Pythonのsubprocessを使ったプログラムを動かしたいです。しかしエラーが出てしまい上手く動きません。何か設定に問題があるのでしょうか。

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

次のようなエラーメッセージが出て実行できません。

ErrorMessage

1Traceback (most recent call last): 2 File "C:\dev\study\python\subproc.py", line 3, in <module> 3 cp = subprocess.run(['ls', '-l'], capture_output=True) 4 File "C:\Users\terai\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 489, in run 5 with Popen(*popenargs, **kwargs) as process: 6 File "C:\Users\terai\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 804, in __init__ 7 errread, errwrite) = self._get_handles(stdin, stdout, stderr) 8 File "C:\Users\terai\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 1142, in _get_handles 9 p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) 10OSError: [WinError 6] ハンドルが無効です。

該当のソースコード

Pythonで外部プログラムを動かす方法を勉強しているところです。外部プログラムの標準出力を受け取ってなにか処理をするために、次のようなプログラムを書きました。

python

1import subprocess 2 3cp = subprocess.run(['ls', '-l'], capture_output=True) 4 5# stdoutの中身を使ってなにかする 6print(cp.stdout.decode('utf-8'))

このプログラムをvim-quickrunを使って実行するとエラーが出ました。

vim-quickrunは、次のように設定しています。

VimL

1" _vimrc 2let g:quickrun_config={ 3 \ '_': { 4 \ 'runner': 'job', 5 \ }} 6set runtimepath+=~/vim-quickrun 7filetype plugin indent on 8syntax enable 9

試したこと

次のような手順で実行をしました。

  1. vim -u _vimrc -N subproc.pyでVimを起動する
  2. \rを入力する

もとのPythonのプログラムが間違っているのかな、と思って、コマンドプロンプトの上で
python subproc.pyと実行したところ、こちらはエラーが出ませんでした。

どういう問題が起きているのでしょうか。また、エラーなく動作させるにはなにか設定が足りないのでしょうか。ご教示いただけますと幸いです。

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

  • OS: Windows 10 (1909)
  • Python: 3.8.2
  • Vim: 8.2.694
  • vim-quickrun: f637c35

修正依頼への対応

otn 2020/05/04 18:08
切り分けのために、下記でどうなりますか? subprocess.run('ls -l <NUL 2>NUL ', shell=True, capture_output=True)

次のようにプログラムを変え、実行しました。

python

1import subprocess 2 3# cp = subprocess.run(['ls', '-l'], capture_output=True) 4cp = subprocess.run('ls -l <NUL 2>NUL ', shell=True, capture_output=True) 5 6# stdoutの中身を使ってなにかする…… 7print(cp.stdout.decode('utf-8'))

実行結果は次の通りで、同じようなエラーが出るようでした。

ErrorMessage

1Traceback (most recent call last): 2 File "C:\dev\study\python\subproc.py", line 4, in <module> 3 cp = subprocess.run('ls -l <NUL 2>NUL ', shell=True, capture_output=True) 4 File "C:\Users\terai\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 489, in run 5 with Popen(*popenargs, **kwargs) as process: 6 File "C:\Users\terai\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 804, in __init__ 7 errread, errwrite) = self._get_handles(stdin, stdout, stderr) 8 File "C:\Users\terai\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 1142, in _get_handles 9 p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE) 10OSError: [WinError 6] ハンドルが無効です。

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

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

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

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

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

otn

2020/05/04 09:08

切り分けのために、下記でどうなりますか? subprocess.run('ls -l <NUL 2>NUL ', shell=True, capture_output=True)
terai

2020/05/04 09:47

コメントありがとうございます。頂いたプログラムの実行結果を末尾に追記いたしました。結果としては同じようなエラーが出るようでした。
otn

2020/05/04 10:47

うーん、そうすると、vim-quickrunを理解しないと解決しそうにないので、お力になれません。
guest

回答1

0

ベストアンサー

job で起動したプロセスの subprocess から STDIN を取得できないためエラーが発生しています。
subprocess はデフォルトで親プロセスのファイルハンドルを引き継ぎますが、Windows での実装は(おそらく)ターミナルの実体がないと子プロセスから STDIN を開けないのだと思います。

vim で対処する場合

  • QuickRun の runner を terminal などにする。

python で対処する場合

  • subprocess で stdin= 引数を指定する。(subprocess.DEVNULLsubprocess.PIPE)

python

1cp = subprocess.run(['ls', '-l'], capture_output=True, stdin=subprocess.DEVNULL)

投稿2020/05/07 12:43

Milly

総合スコア167

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問