8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

XonshAdvent Calendar 2018

Day 21

xonshをつかってみよう

Last updated at Posted at 2018-12-20

xonshとは

Pythonでできたシェル。でもってPythonで書ける。linuxのコマンドとも混在可。
シェルスクリプト??なにそれおいしいのというPythonエンジニアにおすすめ

環境

$ cat /etc/lsb-release 
DISTRIB_ID=elementary
DISTRIB_RELEASE=5.0
DISTRIB_CODENAME=juno
DISTRIB_DESCRIPTION="elementary OS 5.0 Juno"

install

pipでもaptでもインストールできます
$ sudo pip install xonsh (python2と3が混在している場合pip3かな?)
or
$ sudo apt install xonsh

で、注意
aptでインストールすると、古いバージョンがインストールされます。
最新版は今0.8.4ですが、多分0.6.0とかが入ると思います。
アプデでPythonの機能が使えるようになってたりいろいろあるので、最新の安定版を使うのが望ましいかなと思います。
じゃあpipしよう。
でpipしたら/usr/local/bin/xonshにインストールされます。
これでログインシェルを変更しようとすると

$ chsh
パスワード: 
tia のログインシェルを変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
	ログインシェル [/bin/bash]: /usr/local/bin/xonsh
chsh: /usr/local/bin/xonsh はシェルに指定できません

とか言って来やがります。
というわけでxonshをシェルと認めさせるためには/etc/shellsに追記します

# /etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
# 追記
/usr/local/bin/xonsh

これで$ chshでいけるはず

設定ファイルいじるのコワイって人は、aptしたあとにpipすると、2つ(/usr/bin/xonsh, /usr/local/bin/xonsh)インストールされちゃいますが、なぜかusr/bin/xonshの方(aptではいるやつ)のxonshのバージョンも最新になってます。これでchsh -s /usr/bin/xonshでいけるはず

使ってみよう

$ echo hoge
hoge
$ ls
Documents   Music   Public   Templates   Downloads   Pictures   Videos
$ pwd
/home/tia

という感じに、いつものコマンドはいつものように使えます。
で、Pythonが書けるとどういうことか。

$ print('hoge')
hoge
$ import os
$ os.name
'posix'
$ for i in range(5):
.   print(i)
.
0
1
2
3
4

という感じになります。
いつものシェルとして動作するのをsubprocessモード、pythonとして動作するのをpythonモードとか言います。
で、なにが嬉しいかというとpythonのstrとsubprocessの文字列の相互運用ができること

python str から subproess string

$ echo @(2 ** 10)
1024

subprocess から python

$ print($(ls))
Documents
Music
Public
Templates
Downloads
Pictures
Videos

はい。

まあ実際いれて触ってみてもらえば早いと思います。
$()でsubproccess string からpython str または subproccess string

$ echo $(3 * 4)
12
$ echo $(ls)
Documents
Music
Public
Templates
Downloads
Pictures
Videos

$[]でsubprocessを実行、結果を表示、返り値はNone

$ a = $[echo a]
a
$ a
$ a is None
True

!()でsubprocessのclassが返ってくる

$ p = !(pwd)
$ p
CommandPipeline(stdin=<_io.BytesIO object at 0x7f8d126014c0>, stdout=<_io.BytesIO object at 0x7f8d126010a0>, stderr=<_io.BytesIO object at 0x7f8d12601360>, pid=5776, returncode=0, args=['pwd'], alias=None, stdin_redirect=['<stdin>', 'r'], stdout_redirect=[4, 'wb'], stderr_redirect=[12, 'w'], timestamps=[1544454131.2289853, 1544454132.1424832], executed_cmd=['/bin/pwd'], input=, output=/home/tia
, errors=None)
$ p.output
'home/tia\n'

![]でsubprocessを実行、結果を表示、classが返ってくる(HiddenCommandPipelineってやつ)

$ p = ![pwd]
/home/tia
$ p
$ type(p)
xonsh.proc.HiddenCommandPipeline
$ p.returncode
0

@()でpythonからsubprocess
リストを指定すると順番に実行してくれる

import xonsh
$ echo @(xonsh.__version__)
0.8.3
$ l = [1,2,3,4,5]
$ touch @(l)
$ ls
1   2   3   4   5   (省略)

for文とかの中にも全然書ける

$ for i in range(1,5):
.   touch @(i)
.
$ ls
1   2   3   4   5   (省略)

コマンドを書く

コマンドもPythonで書ける

def _my_echo(args, stdin=None):
    print(' '.join(args))

$ aliases['my_echo'] = _my_echo

関数を書いて、エイリアスを貼るとコマンドとして使えるようになる。
関数名とエイリアス名を被せないように注意
引数は、ひだりから 
args: 引数がリストに入ってる
stdin :
stdout:
stderr: 名前の通りのファイルオブジェクトが流れてくる

あとまだあるらしいけど、この辺から先は自分がまだ把握できてないので、ptk(ぷろんぷとつーるきっと)とかって調べると幸せになれると思う。

これで例えば(僕が使ってる)ターミナルからgoogle翻訳に飛べるやつ
デフォルトで英語から日本語
-jオプションで日本語から英語
manコマンドの結果をそのまま流して見るとかもできる

def _trans(args, stdin=None):
    from urllib.parse import quote
    from time import sleep

    options = [(index, value) for index, value in enumerate(args) if value[0] == '-']
    options.reverse()
    for i, v in options:
        del args[i]
    
    if '-j' in [v for _, v in options]:
        url = 'https://translate.google.com/?hl=ja&tl=en&text='
    else:
        url = 'https://translate.google.com/?hl=ja&tl=ja&text='

    if stdin is None:
        if not args:
            print('trans {arg[0]}')
            print('_trans(args)')
            return 1
        for w in args:
            text = quote(w)
            chromium-browser @(url+text)
            sleep(1)
    else:
        while True:
            text = quote(stdin.read(5000))
            if text == '':
                break
            chromium-browser @(url+text)
            sleep(1)

まとめて

基本はいつものPythonとLinuxのコマンドです。
あとは、僕自身まだxonshをxonshらしく使いこなせてはいないので、精進します・・・という感じですが・・・
Python大好き他の言語なんてよほどのこと(モバイル開発とか)がないと使いたくない、みたいな人にはとてもおすすめです。なぜなら僕がそうだから

8
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?