Python subprocess

何を今更だけど os.system や os.popen はもう「使うな!」なんだね。
17.1. subprocess ? サブプロセス管理 ? Python 2.7ja1 documentation

それどころか Python3 には commands が無い。
subprocess の使いかたを覚えておかなければ。

# command

import os
import subprocess

#os.system("gvfs-open hoge.txt")
subprocess.call(["gvfs-open", "hoge.txt"])

# With spaces in the file names
#os.system('gvfs-open "on space.txt"')
subprocess.call(["gvfs-open", "on space.txt"])

引数の最初が args だから list に全部入れなきゃだめってことみたい。
ファイル名にスペースがある場合に楽になった、ような…

それからえっと
os.system(“gedit &”)
みたいなバックグラウンド実行はどうするのかな。

# Background

#subprocess.call(["gedit", "&"]) # Error
subprocess.Popen(["gedit"])

Popen を選ぶだけみたい、ふむふむ。

でコマンドのアウトプットを得るには

# Get Output

#output = os.popen("pwd").read()
#output = commands.getoutput("pwd")
output = subprocess.check_output(["pwd"])

なるほど。

ということでこんなページを作ってみた。
Python Tips – L’Isola di Niente

でも結局 GLib を使ったほうが楽だったりして。
全部 Python でやることにこだわるなんて正直アホみたい。

from gi.repository import GLib

# Execute
GLib.spawn_command_line_async("gvfs-open hoge.txt")
# Get Output
result, output, error, status = GLib.spawn_command_line_sync("ls -l")
print output

Gtk+ DataBinding

明日から仕事始めなのでと覚書ページ書き換えラストスパート。
GtkSwitch を試していて困った。

GtkSwitch

activate シグナルがあるけど connect しても発行されない。
but use the notify::active signal.
なんて書いてあるから当然なんだけど、どう使うの?
さて今日も英語と格闘が始まるな。

Short Example of GSettings Bindings with Python using a Gtk Switch ? Mariano Chavero

なるほど、こうやって使うのか。
GNOME3 環境の人しか実験できないサンプルだけど on off でデスクトップアイコンの表示切り替えができるのを確認した。
しかも dconf-editor で切り替えたら GtkSwitch も切り替わる双方向。

つまり Widget のプロパティと GSettings はバインディングできるんだね。
それなら Widget 同士でもやれそうだと思ったので調べてみる。
というか GSettings のサンプルだと GNOME3 以外を使っている人には解らないし。

GBinding

g_object_bind_property という関数で Widget 同士のバインドもできそう。
PyGI で GObject.Binding 内を探すが見当たらない。

GObject-2.0 Python API Documentation

うーんココには有ると書いているんだけど。
って URL をよく見たら ubuntu-12.10 だ、つまり Fedora17 より新しい。
仮想 Ubuntu 12.10 を立ち上げ dir してみる。

bind_property

あぁやっぱり。
しかたがない、今は仮想 Ubuntu 上で試してみるか。

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

"""
    Widget Property Binding Sample
"""

from gi.repository import GObject, Gtk

switch = Gtk.Switch()
check = Gtk.CheckButton("Check")
GObject.Binding.bind_property(
        switch, "active",
        check, "active",
        GObject.BindingFlags.BIDIRECTIONAL )

hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
hbox.pack_start(switch, False, False, 0)
hbox.pack_start(check, False, False, 0)

w = Gtk.Window()
w.add(hbox)
w.connect("delete-event", Gtk.main_quit)
w.show_all()
Gtk.main()

widget_property_binding

GBindingFlags は
GObject.BindingFlags.DEFAULT では source 側からの一方向バインド。
GObject.BindingFlags.BIDIRECTIONAL で双方向になる。
他2つはよく解らない、上記2つあれば充分だし。

こんな感じでデータと GUI を結びつければ面白くなるね。
WPF の ObservableCollection みたくできるかも、アレは混乱の元だが。

しかし早く fedora 18 出ないか、今日サイトを見たら又伸びているんだが…

Fedora 17 BD-R

もうすぐ Fedora 18 が出る、導入するマシンの準備をしなければ。
Core i 何とかあたりに変えようか考えたけどまだ現 4 コア phenom は使えるし。
もったいないから壊れるまで HDD 取り替えのみで使うことにする。

でもかなり前から壊れている DVD ドライブだけはいいかげんに変えなければ。

ただ買い換えるだけでは面白くないので Blu-ray ドライブを買った。
検索すると普通に Brasero で書き込み Nautilus で観覧できるみたいなので。

とりあえず上記を買って壊れた LG の DVD ドライブと取り替える。
空の BD-R を入れると CD, DVD ディスク同様に自動マウント、うんうん。
早速 Brasero で書き込みしてみる。

brasero_error

なんだよ、トレイが勝手に吐き出されてコレだよ。

ログ

Checking session consistency (brasero_burn_check_session_consistency brasero-burn.c:1739)
Unsupported type of task operation
Session error : 内部エラーが発生しました (brasero_burn_record brasero-burn.c:2856)

エラーログの内容で検索すると当然のように海外しかヒットしない。
しかも Ubuntu ばかりだし症状が一致しない、Fedora のデスクトップ利用はメジャーでは無いと解っているがチョッピリ悲しい。
結局原因は解らない。

というか、日本語で検索しても再生のこと以外ヒットしない。
インストールと観覧しかやらないなら絶対に Windows のほうが便利だぞ。
書き込みできなくてもアプリに文句言えばいいだけだしね。

Ubuntu日本語フォーラム / ブルーレイディスクにデータを書き込むソフトウエアはありますか ?

日本語でまともなのが見つかるのはやはりココくらいなものか。
K3b ってので書き込めるみたい、面倒なのでコレ入れてみる。
なんかイッパイインストールされてしまったんだが、おまえは iTunes か!

growisofs を次 Fedora でも書き込めないなら試すことにしよう。
PyGI で GUI を作って os.system(str) なんてのを作れば充分そうだしね。
Brasero で問題なければいいわけだが。

まあとにかく書き込んでみる。
とりあえず全部デフォルト設定のままで合計約 20GB のデータを。

k3b_jp

12 倍速と書いているのに 2 倍速以上にはならないんですけど。
外付け USB HDD のほうがストレスが少ない、でも信頼性を考えると…
データ次第で使い分けすればいいことだが。

書き込み完了でエラー、コレは以前のドライブと同じだけどケーブルが悪いのか?
一旦取り出して再び挿入、Nautilus で普通に自動マウントされファイルが読める。
書き込み自体は問題なく行われたようだ。

ということで K3b は普通に BD-R 書き込みできます、困ったらコレ。

それよりこのドライブって恐ろしく静かだ。
試しに CD を聴いてみると本当に回っているのか不安になるくらい。
こういうのはやっぱり日本メーカーを選ばないと駄目だね。

********************

ついでに。
先月のことだけど二年使った Logicool M505 マウスが壊れたので電気屋へ。
たった千二百円の投げ売り Microsoft マウスを見つけたので思わず買った。
初めての Microsoft マウスだ、さあどうだ。

軽すぎて手に馴染まない。
ホイールのクリック感が皆無。
サスペンドがマウスを動かしただけで何故か復帰するように。
そのせいかアルカリ電池が一週間しか持たない。

そのうち慣れるだろうと一ヶ月我慢したけど限界だ!
特に電池は M505 は半年持っていたぞ!

少し大きめのほうががいいかなとやっぱりこの安い奴に買い換えた。
あぁ握り心地は最高だしマウスを動かしても復帰しないのがこんなに嬉しいとは。
もう絶対に割高でも Logicool 以外は買わないことにする。

Gtk SetForegroundWindow

年末年始の空き時間を使って覚書ページまとめと Tips 追加をやっている。
ついでに HDD 内の古いサンプルコードを整理。

ほぼ PyGtk コード、ほとんどもう役に立たない…
GTK3 には Pixmap なんてもう無いっつーのとか。
千以上あったけどやっと 2/3 くらいに減らした。

でも中には今まで気がつかなかったコードも見つかる。
多重起動防止でアプリを最前面にもっていく方法が今まで解らなかった。

gtk_window_activate_focus ()
gtk_window_present ()

どうやらこの二つを呼べばアクティブ化できるようだ。
以前書いた GtkApplication を使った Vala コードを書き換えて実験。

using Gtk;

/*
 * Prevent multiple window Sample
**/
public class TestWin : Window {

    private Notebook note;
    private TextView[] view;

    public TestWin ( Gtk.Application app ) {
        this.set_application ( app );
        this.set_title( "TestWin" );
        note = new Notebook ();
        this.add ( note );
        this.resize ( 320, 240 );
        this.show_all ();
    }
    public void CreateNew () {
        var tab_label = new Label ( "new.txt" );
        var text_view = new TextView ();
        view += text_view;
        note.append_page (text_view, tab_label);
        this.show_all ();
        // New Page Activate
        note.set_current_page ( view.length - 1 );
    }
    public void CreateTab ( File[] files ) {
        foreach ( var file in files ) {
            var tab_label = new Label( file.get_basename () );
            var text_view = new TextView ();
            view += text_view;
            note.append_page(text_view, tab_label);
        }
        this.show_all();
        // Last Page Activate
        note.set_current_page ( view.length - 1 );
    }
}

public class App : Gtk.Application {

    private TestWin win = null;

    public App () {
        Object (application_id:"apps.test.helloworld", flags:ApplicationFlags.HANDLES_OPEN );
    }
    public override void activate () {
        if ( win == null ) {
            win = new TestWin( this );
        }
        win.CreateNew ();
        // SetForegroundWindow
        win.activate_focus();
        win.present();
    }
    public override void open ( File[] files, string hint ) {
        if ( win == null ) {
            win = new TestWin( this );
        }
        win.CreateTab ( files );
        // SetForegroundWindow
        win.activate_focus();
        win.present();
    }
}

public class Main {
    public static int main ( string[] args ) {
        Gtk.init ( ref args );
        var app = new App ();
        app.run ( args );
        return 0;
    }
}

ついでに追加タブもアクティブにするコードも入れてみた。
うん、今のところこれでいけるようだ。
多重起動防止アプリ以外ではどうでもいいことなんだけどね。

コンパイルするの面倒くさいよ、早く PyGI で使えるようになってくれ。

Vala GtkDrawingArea

古いコンテンツの覚書のページ書き換えをヤルヤル詐欺していた。
放置しすぎてもう古さ全開なのでと先週から地味に整理中。
この年末年始休暇の内になんとか整理を終わらせたい。

ウインドウを作る – L’Isola di Niente
ダイアログを作る – L’Isola di Niente

コレのために Glade を何年かぶりに入れたりしたけど特にネタも無かった。
Glade を使ったページは削除で済ませることにしよう。

次は DrawingArea を、PyGtk と共通点がゼロなんだよなココ。
expose-event が draw に変わって cairo_t を使えだもんな。

しかし困った、Fedora 17 では下記 PyGI コードが動かない。
というか draw のシグナルが発生しない。

原因判明、同一ディレクトリに cairo.py なんて名前のファイルを入れていたので上書き扱いになり cairo.Context が見つからず変換できないエラーでシグナルが作成できなかっただけだった…
消したら普通に動いた…

Python with GTK+3.0 Create GtkPixbuf | PaePoi

GTK+ 3.4 自体がおかしいのか gir がおかしいのかな。
Boxes 上の仮想 Ubuntu は GTK+3.6 なのでソッチで動かしてみる。

gtk3_6

問題なく動く、こりゃココの整理は Fedora 18 待ちか。
せっかくなので Vala で同じコードを書いてみた。

PyGI では入れていなかった画像が無かった場合の例外処理も入れて。
以前書いた MessageBox.Show() の使い方サンプルも兼ねて。

using Gtk;
using Gdk; //Pixbuf

/*
 * build command
 * valac --pkg gtk+-3.0 test.vala
 * `--pkg gdk-2.0` Not required
 */

public class Win : Gtk.Window {

    private Pixbuf pixbuf;
    private DrawingArea drawing_area;

    public Win () {
        this.set_title("draw test");
        this.destroy.connect (Gtk.main_quit);
        // DrawingArea
        drawing_area = new DrawingArea();
        drawing_area.draw.connect(on_drawing_area_draw);
        try {
            pixbuf = new Pixbuf.from_file("madoka.jpg");
        } catch (Error e) {
            MessageBox.Show(e.message);
        }
        this.add(drawing_area);
        this.show_all();
    }

    private bool on_drawing_area_draw(Cairo.Context cr) {
        // set picture
        if (pixbuf != null)
            Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
        // Arc
        int width = drawing_area.get_allocated_width();
        int height = drawing_area.get_allocated_height();
        cr.arc( width / 2.0,
                height / 2.0,
                int.min(width, height) / 2.0,
                0,
                2 * Math.PI);
        cr.fill();
        return false;
    }
 
    public static int main (string[] args) {
        Gtk.init(ref args);
        new Win();
        Gtk.main();
        return 0;
    }
}

public class MessageBox {
    public static ResponseType Show (string text) {
        var dlg = new MessageDialog(
                null,
                DialogFlags.MODAL,
                MessageType.ERROR,
                ButtonsType.OK,
                text );
        dlg.set_title("Message");  
        var res = dlg.run();
        dlg.destroy();
        return (ResponseType)res;
    }
}

gtk3_4_vala

Vala では GdkPixbuf.Pixbuf ではなく Gdk.Pixbuf なんだね。
gir って実はよく解っていないけど動的と静的で違うのか。
PyGI では GLib.PI だったのが GLib.Math.PI だったりとか思ったより迷う。
min 関数は int.min() とかって何だよ…
ほとんど同じだけど実は細かく違うのね。

このコードは PyGI っぽくハンドラを書いたけどハンドラに GtkWidget 部を入れられないのでクラス変数を使うしかなく少し面倒、公式サンプルのように書いた方がローカル変数が使えて楽かと。
pkg 指定が Gtk+-3.0 だけでイケたのがちょっと奇妙。

とりあえず GTK+ 3.4 環境でも Vala なら問題なく draw シグナルが使えるってことですね。

しかし古いページはたった三年前に書いたとは思えない古臭さだ。
又あと三年たったら…考えないようにしよう。
最近の Linux は進化が早すぎて怖い。

アプリケーションの.NET Framework 4.5への移行: 廃止された型と新しい型

とはいえ .NET に比べたら楽なもんだ。
969 の新しい public 型なんて吐き気しかしない、Linux へ早めに逃げて良かった。
.NET 関連の tips も削除しといたほうがいいのかも。