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

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

ただいまの
回答率

90.51%

  • Python

    11700questions

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

  • Linux

    4428questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • Ubuntu

    1802questions

    Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

サブプロセスでsudo lsusbを実行したいのですが、現状落ちてしまいます。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,106

morutemu

score 33

USBの給電制御するようなプログラムです。

OS:Lubuntu16.04
python:3.52

エラー内容

Traceback (most recent call last):
File "/home/ユーザー名/USB給電制御.py", line 102, in <module>
ret = subprocess.check_output(cmd, shell = True)
File "/usr/lib/python3.5/subprocess.py", line 626, in check_output
**kwargs).stdout
File "/usr/lib/python3.5/subprocess.py", line 708, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'sudo lsusb' returned non-zero exit status 1

ソースは以下の通りです。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# ++++++++++++++++++++++++++++++++++++++++ モジュール +++++
from tkinter import *
from tkinter import ttk
from time import *
import subprocess

# ++++++++++++++++++++++++++++++++++++++++ ウィンドウ +++++
root = Tk()
root.geometry('350x200')
root.title('USB給電制御')
root.option_add('*font', ('Helvetica', 10))
root.resizable(0,0)

# ++++++++++++++++++++++++++++++++++++++++ 関 数 +++++
# 現在時刻の処理
def CurrentTime():
    # グローバル変数を指定
    global currentTime
    global onTime
    global offTime
    # 現在時刻をセットする
    currentTimeVal.set(strftime('%H:%M:%S'))
    # ON/OFF時間を代入する
    onHour = onHourVal.get()
    onMin = onMinVal.get()
    onSec = onSecVal.get()
    offHour = offHourVal.get()
    offMin = offMinVal.get()
    offSec = offSecVal.get()
    # 現在・ON/OFF時間をグローバル変数に代入する
    currentTime = currentTimeVal.get()
    onTime = onHour + ':' + onMin + ':' + onSec
    offTime = offHour + ':' + offMin + ':' + offSec
    # 一定時間で繰り返す
    root.after(1000, CurrentTime)

# ON/OFFの処理
def powerProc(power):
    # コマンドリストを初期化
    cmdList = []
    # 選択されているHUB名称を取得
    hubName = hubNameVal.get()
    # HUB選択で初期項目(選択してください)だった場合
    if hubName == initialHubName:
        return
    # コマンドリストを作成する
    for i in retList:
        # バス・デバイス・ポート番号を取り出す
        bus = i[4:7].lstrip('0')
        device = i[15:18].lstrip('0')
        port = portVal.get()
        # マッチングするリスト番号を特定
        if i.find(hubName) > -1:
            matchIndex = retList.index(i)
        # コマンドに当てはめてリストに保存する
        cmdList.append('sudo ./hub-ctrl -b ' + bus + ' -d ' + device + ' -P ' + port + ' -p ' + power)
    # コマンドを実行する
    subprocess.call(cmdList[matchIndex], shell=True)

# 指定時間ONの処理
def TimeOn():
    # ONにチェックが入っている場合
    if onVal.get():
        # 指定時間ONと現在時刻が一致した場合
        if onTime == currentTime:
            # ON
            power = '1'
            powerProc(power)
    # 一定時間で繰り返す
    root.after(1000, TimeOn)

# 指定時間OFFの処理
def TimeOff():
    # OFFにチェックが入っている場合
    if offVal.get():
        # 指定時間OFFと現在時刻が一致した場合
        if offTime == currentTime:
            # OFF
            power = '0'
            powerProc(power)
    # 一定時間で繰り返す
    root.after(1000, TimeOff)

# 強制ONの処理
def ForceOn():
    # ON
    power = '1'
    powerProc(power)

# 強制OFFの処理
def ForceOff():
    # OFF
    power = '0'
    powerProc(power)

# ++++++++++++++++++++++++++++++++++++++++ 初期動作 +++++
# 入力コマンドのセット
cmd = 'sudo lsusb'
ret = subprocess.check_output(cmd, shell = True)
# 結果をデコードしてStringに変換
decRet = ret.decode('utf-8')
# 最後の\nを削除
slcRet = decRet[:-1]
# \nで区切ってリストに入れる
retList = slcRet.replace("'","").split('\n')
# 区切ったリストの文字からBus・Device・IDを削除する
retNameList = [val[33:] for val in retList]

# ++++++++++++++++++++++++++++++++++++++++ 変 数 +++++
# ラベル
currentTimeVal = StringVar()

# コンボボックス
hubNameVal = StringVar()
initialHubName = '選択して下さい'
hubNameVal.set(initialHubName)

# チェックボックス
onVal = BooleanVar()
offVal = BooleanVar()
onVal.set(True)
offVal.set(True)
onCheck = ''
offCheck = ''

# スピンボックス
portVal = StringVar()
onHourVal = StringVar()
onMinVal = StringVar()
onSecVal = StringVar()
offHourVal = StringVar()
offMinVal = StringVar()
offSecVal = StringVar()
onHourVal.set('06')
onMinVal.set('00')
onSecVal.set('00')
offHourVal.set('18')
offMinVal.set('30')
offSecVal.set('00')

# その他
currentTime = ''
onTime = ''
offTime = ''

# ++++++++++++++++++++++++++++++++++++++++ リスト +++++
# コマンド
cmdList = []

# ラベル
labelPositions = [
    {'text' : '現在時刻', 'textvariable' : '', 'x' : 30, 'y' : 20},
    {'text' : '対象HUB/Port', 'textvariable' : '', 'x' : 30, 'y' : 50},
    {'text' : ':', 'textvariable' : '', 'x' : 164, 'y' : 80},
    {'text' : ':', 'textvariable' : '', 'x' : 213, 'y' : 80},
    {'text' : ':', 'textvariable' : '', 'x' : 164, 'y' : 110},
    {'text' : ':', 'textvariable' : '', 'x' : 213, 'y' : 110},
    {'text' : '', 'textvariable' : currentTimeVal, 'x' : 130, 'y' : 20}
]

# コンボボックス
comboboxPositions = [
    {'values' : retNameList, 'textvariable' : hubNameVal, 'state' : 'readonly', 'width' : 17, 'x' : 130, 'y' : 50}
]

# ボタン
buttonPositions = [
    {'text' : '強制ON', 'command' : ForceOn, 'width' : 8, 'x' : 130, 'y' :150},
    {'text' : '強制OFF', 'command' : ForceOff, 'width' : 8, 'x' : 230, 'y' :150}
]

# チェックボックス
checkButtonPositions = [
    {'varName' : onCheck, 'text' : 'ON', 'variable' : onVal, 'x' : 30, 'y' : 80},
    {'varName' : offCheck, 'text' : 'OFF', 'variable' : offVal, 'x' : 30, 'y' : 110}
]

# スピンボックス
spinBoxPositions = [
    {'from' : 1, 'to' : 4, 'increment' : 1, 'format' : '', 'textvariable' : portVal,'with' :2, 'x' : 280, 'y' : 50},
    {'from' : 0, 'to' : 23, 'increment' : 1, 'format' : '%02.0f', 'textvariable' : onHourVal, 'with' :2, 'x' : 130, 'y' : 80},
    {'from' : 0, 'to' : 59, 'increment' : 1, 'format' : '%02.0f', 'textvariable' : onMinVal, 'with' :2, 'x' : 180, 'y' : 80},
    {'from' : 0, 'to' : 59, 'increment' : 1, 'format' : '%02.0f', 'textvariable' : onSecVal, 'with' :2, 'x' : 230, 'y' : 80},
    {'from' : 0, 'to' : 23, 'increment' : 1, 'format' : '%02.0f', 'textvariable' : offHourVal, 'with' :2, 'x' : 130, 'y' : 110},
    {'from' : 0, 'to' : 59, 'increment' : 1, 'format' : '%02.0f', 'textvariable' : offMinVal, 'with' :2, 'x' : 180, 'y' : 110},
    {'from' : 0, 'to' : 59, 'increment' : 1, 'format' : '%02.0f', 'textvariable' : offSecVal, 'with' :2, 'x' : 230, 'y' : 110}
]

# ++++++++++++++++++++++++++++++++++++++++ オブジェクトの配置 +++++
# ラベル
for i in labelPositions:
    Label(root, text = i['text'], textvariable = i['textvariable']).place(x = i['x'], y = i['y'])

# コンボボックス
for i in comboboxPositions:
    ttk.Combobox(root, values = i['values'], textvariable = i['textvariable'], state = i['state'], width = i['width']).place(x = i['x'], y = i['y'])

# ボタン
for i in buttonPositions:
    Button(root, text = i['text'], command = i['command'], width = i['width']).place(x = i['x'], y = i['y'] )

## チェックボックス
for i in checkButtonPositions:
    i['varName'] = Checkbutton(text = i['text'], variable = i['variable']).place(x = i['x'], y = i['y'])

# スピンボックス
for i in spinBoxPositions:
    Spinbox(root, from_ = i['from'], to = i['to'], increment = i['increment'], format = i['format'], textvariable =i['textvariable'], width = i['with']).place(x = i['x'], y = i['y'] )

# ++++++++++++++++++++++++++++++++++++++++ 関 数 +++++
# 現在時刻
CurrentTime()

# 指定時間ON
TimeOn()

# 指定時間OFF
TimeOff()

# ++++++++++++++++++++++++++++++++++++++++ ウィンドウ表示 +++++
root.mainloop()
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

これは結構難しい問題です。

lsusbが0以外を返すのは間違いなく、管理者権限が取れていないためです。

回避する方法は色々あります。

  • subprocessstdinにパスワードを流し込む方法
  • python自体に管理者権限をもたせる方法

この方法で最も汎用性があるのはsubprocessstdinにパスワードを流し込む方法ですが、Tkinterでパスワード入力画面を作って、stdinに流し込む必要があります。
非常に面倒ですが、どのディストリビューションでも動く汎用性があります。

もうひとつはpython自体に管理者権限をもたせる方法です。
こちらは簡単ですが、ディストリビューションごと(正確にはWindowManagerごと)に方法が違います。

Lubuntuでは以下のコマンドでスクリプトを起動すればよいと思います。

gksudo ./USB給電制御.py

ちなみにopenSUSE+KDEですと、以下のコマンドになります。

kdesu ./USB給電制御.py

このコマンドで起動すると、GUIで管理者パスワードを求めてきますので入力してください。
ですので適当なshファイルを作成して、上記のコマンドを書いてください。

少なくともopenSUSEでは、この方法でDolphinからダブルクリックで起動できました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/31 06:54 編集

    前回といい、非常にわかりやすい解説ありがとうございます。
    初めてpythonを触り、初めて自分でプログラムを組んだものなので、現状パスワードを入れる高度なことはちょっと少し難しそうなので、後者のpython自体に管理者権限をもたせる方法を実施してみました。

    kdesudo ./USB給電制御.py

    で実行してみたところパスワード入力画面が出てきて、パスワードはできました。
    しかし、ターミナルに文字化けしたものが出てきてしまい、ダブルクリックでの起動はできませんでした。

    キャンセル

  • 2017/05/31 07:43

    最後のkdesuだけ試してみてください。
    まぁ、この問題はPythonというよりLinux(KDE)の問題なので難しいですね。

    キャンセル

  • 2017/05/31 16:27

    kdesu:コマンドが見つかりません

    と、出てきました

    キャンセル

  • 2017/06/01 07:25 編集

    gksudoはどうでしょうか?
    これなら行けると思います。

    キャンセル

  • 2017/06/03 01:36

    すみません、回答していただいていたのに、遅くなりました。
    gksudo ./USB給電制御.py
    こちらで実行してみました。
    一応パスワードを入れるところまではでき、文字化けも出ませんでした。
    ただ、ダブルクリックでの実行はできませんでした。

    前にも教えていただいたパスワードを入力する方法を考えるしかなさそうですね。

    キャンセル

  • 2017/06/03 07:44 編集

    うーん、それでいけるはずなんですが・・
    .shファイルを作りましたよね?
    .shファイルをダブルクリックでいけませんか?
    .shファイルを作っても.pyをダブルクリックしていたのでは意味がありませんよ?

    キャンセル

  • 2017/06/03 09:13

    .shファイルを作るのは知りませんでした。。
    で、一応調べてやってみたんですが、うまくいきませんでした。

    ◆手順
    ①shellファイルを作成
    USB給電制御.sh(home/ユーザーネーム/デスクトップにあります)
    中身:
    #!/bin/gksu root
    sudo python /home/ユーザーネーム/ USB給電制御.py

    ②実行ファイルにする
    chmod +x USB給電制御.sh

    ③USB給電制御.shをダブルクリックして起動
    ウィンドウを起動

    実行 ⇒ 起動せず
    端末で実行 ⇒ ターミナルが出て来ましたが、特に何も起こりませんでした。

    キャンセル

  • 2017/06/03 11:17

    shファイルの中身は

    gksudo /home/ユーザーネーム/ USB給電制御.py

    で良いはずです。

    キャンセル

  • 2017/06/03 12:51 編集

    shファイルを

    USB給電制御.sh
    gksudo /home/ユーザーネーム/ USB給電制御.py

    にして実行してみたところ。

    Enter your password to perform administrative tasks
    The application '/home/ユーザーネーム/'USB給電制御'' lets you modify essential partss of your system

    とパスワード入力を求められ入力してましたが、ダメでした。

    キャンセル

  • 2017/06/05 20:35

    基本的に"gksudo xxx.py"がターミナル上で実行可能であれば、それを.shファイルにしただけなので、同じ動作をするはずなんですが・・・
    これ以上は私にはわかりません、あと少しな気がするのですが・・・
    力になれなくて申し訳ありません。

    キャンセル

  • 2017/06/07 17:09 編集

    いえいえ、こんなに尽力していただきありがとうございます。

    一応パソコン得意な友人に聞いたところ、.desktopで起動できるようでした。

    [Desktop Entry]
    Type=Application
    Terminal=true
    Name=USB給電制御
    Icon=utilities-terminal
    Exec=lxterminal -e "bash -c 'sudo -s python3 /home/ユーザー名/USB給電制御.py;$SHELL'"
    Categories=Application;

    キャンセル

  • 2017/06/08 09:36

    起動できるようになってよかったです。
    最初、LubuntuをKubuntuと勘違いしており、再現できない環境で回答してしまったため、心配しておりました。
    勉強になります。

    キャンセル

+1

コードを書きたかったので回答欄を使います。以下のコードをの実行結果が原因を突き止めるために有用だと思います。

from subprocess import run
from subprocess import PIPE


try:
    print(run('sudo lsusb', stdout=PIPE, stderr=PIPE))
except Exception as e:
    print(e)
    print(e.args)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • Python

    11700questions

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

  • Linux

    4428questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

  • Ubuntu

    1802questions

    Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。