読者です 読者をやめる 読者になる 読者になる

HPCメモ

HPC(High Performance Computing)に関連したりしなかったりすることのメモ書き

mac 上で vagrant + ansibleの環境構築

前回は、ホストマシンとしてWindows10を使った環境を作りましたが、そろそろLinux環境をゲストにしたものも必要になってきたのでサクっと作ってみました。

hpcmemo.hatenablog.com


既に入っているものもありますが、必要なソフトをbrewでインストールします。

> brew install Caskroom/cask/vagrant Caskroom/cask/vagrant-manager vagrant-completion \
                        Caskroom/cask/virtualbox Caskroom/cask/virtualbox-extension-pack ansible

今回はCentOS7で環境を作る必要があったので、こちらの記載を参考にvagrant initします。
Vagrant box centos/7 | Atlas by HashiCorp

> vagrant init centos/7

Vagrantfileにはとりあえずvirtualboxのメモリ設定だけ追加して、あとは仮に"site.yml"というplaybookの名前を指定しておきます。

$ cat Vagrantfile 
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.ssh.insert_key = false
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.memory = "4096"
  end
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "./site.yml"
  end
end

最後にこのsite.ymlを作っていきます。といっても今回は単純な開発環境なので、こんな感じでyumを使っていくつかのパッケージを入れるだけの簡単なplaybookです。

$ cat site.yml 
- hosts: all
  tasks:
  - name: install basic tools for build C/C++/Fortran program
    become: yes
    yum:
      name: "{{item}}"
      state: latest
      update_cache: True
    with_items:
      - cmake
      - autoconf
      - automake
      - git
      - gcc.x86_64
      - gcc-c++.x86_64
      - gcc-gfortran.x86_64

ターゲット環境が毎回微妙に変わるので*1この辺のツールをインストールするところはroleにして再利用できるようにしておくと大変便利そうです(でもやってない)

*1:CentOS or RHELのバージョンが 6だったり5だったり、たまにUbuntuの時もあるけど

vagrant で modernIE

「せっかくだから、俺はこの銀の弁当箱を選ぶぜ!」くらいの勢いでMac miniを導入した私ですが、初っ端からwindows環境のお客様が続いています・・・
MSDNを導入するには予算オーバーだし、Macを買ってそうそうにwindowsのパッケージを買うのも負けた感があるので、modern IEで配ってるVMを使ってテスト環境を作るのが一番手っ取り早いんですが*1、ちょっと前まではvagrantから使うには一手間必要でした。

Setup modern.ie vagrant boxes · GitHub

が、いつの間にかMicrosoftからvagrantの形式でダウンロードできるようになっていたようです。

developer.microsoft.com

"Virtual Machine"のドロップダウンリストから必要なブラウザ&OSの組み合わせを選び、select platformの方のドロップダウンリストから"Vagrant"を選んで、下にある"Download Zip"ボタンを押すとVMをダウンロードすることができます。ただし、帯域制限しているのかうちの環境のせいかは不明ですが、1〜2MB/sec程度の転送レートになっちゃうので、ダウンロードするのに1時間くらいはかかります。*2


ひととおり、ダウンロードしてzipファイルを解凍するとこんな感じになります。

$ ls -s1
total 103168888
5017546388 IE10 - Win7.box
5017546668 IE10.Win7.Vagrant.zip
7378661428 IE11 - Win81.box
7378661710 IE11.Win81.Vagrant.zip
4496872696 IE8 - Win7.box
4496872974 IE8.Win7.Vagrant.zip
4800376728 IE9 - Win7.box
4800377006 IE9.Win7.Vagrant.zip
4717767002 MSEdge.Win10_RS1.Vagrant.zip
4717766724 dev-msedge.box

圧縮の意味が無いのはお約束 :p


とりあえずMS Edge+Win10のものを起動してみましょう。
最初にbox addコマンドでboxを追加しておきます。

 vagrant box add MSEdgeWin10 ./dev-msedge.box 
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'MSEdgeWin10' (v0) for provider: 
    box: Unpacking necessary files from: file:///Users/sogo/modernIE/dev-msedge.box
==> box: Successfully added box 'MSEdgeWin10' (v0) for 'virtualbox'!

続いて、適当なディレクトリを作成してvagrant initでVagrantfileを作成します。

$ mkdir test
$ cd test
$ vagrant box list
MSEdgeWin10 (virtualbox, 0)
$ vagrant init MSEdgeWin10
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

生成されたVagrantfileを編集して、中ほどにあるGUIの設定とメモリの設定を変更し、vramの設定を追加しておきます。
*3

config.vm.provider "virtualbox" do |vb|
  # Display the VirtualBox GUI when booting the machine
  vb.gui = true
  # Customize the amount of memory on the VM:
  vb.memory = "8192"
  vb.customize ["modifyvm", :id, "--vram", "256"]
end

でもってvagrant upするとvirtual boxのGUI画面が立ちあがって、そっちでWindows10が起動されます。
f:id:n_so5:20170113162619p:plain
コンソール側ではこんな感じで、延々とsshでのアクセスをしようとして失敗しタイムアウトしていますが、GUI使う分には問題無いです。気になる人は"config.vm.boot_timeout=5"とか適当に短いタイムアウト設定をVagrantfileに追加しておけば、コンソール側の処理も早く終わります。

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'MSEdgeWin10'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: WORK_default_1484292217879_22020
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.

If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.

If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.

If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.

しかし、実はこのwindowsゲスト内では、sshdが上がっているようでコマンドプロンプトを開いてlocalhostsshすると入れます。
f:id:n_so5:20170113225238p:plain
せっかく用意してくれてるなら、使わないと申し訳ないので一旦vagrant haltしてVagrantfileに以下の設定を追加しましょう。

config.vm.guest = :windows
config.ssh.username = "IEUser"
config.ssh.password = "Passw0rd!"

vm.questの設定はsshの設定とは直接関係ありませんが、この設定を入れておかないとログインしてsudoしようとして次のようなエラーを吐いてこけます。

==> default: Mounting shared folders...
    default: /vagrant => /Users/n_so5/Google Drive
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

mkdir -p /vagrant

Stdout from the command:



Stderr from the command:

sh: sudo: command not found

synced folderの設定くらいなら、使わなければ大丈夫なんですが、vagrant haltした時にはsudo shutdown -hしようとしてこけるので致命的です・・・

でもって、この設定を入れてvagrant upすると

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: IEUser
    default: SSH auth method: password
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default: 
    default: Guest Additions Version: 5.0.20
    default: VirtualBox Version: 5.1
==> default: Mounting shared folders...
    default: /vagrant => /Users/n_so5/Google Drive
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.


最終的にできあがったVagrantfileはこんな感じになってます。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "MSEdgeWin10"
  config.vm.guest = :windows

  config.ssh.username = "IEUser"
  config.ssh.password = "Passw0rd!"

  config.vm.provider "virtualbox" do |vb|
    vb.gui = true
    vb.memory = "8192"
    vb.customize ["modifyvm", :id, "--vram", "256"]
  end
end


ん、winrm? 何それ美味しいの?

*1:と思ってたけどAzureにもwindows7/8.1がテスト環境として用意されてるんですね。こっちでも良かったかもしれん・・・

*2:複数のVMを並行してダウンロードしてもこの転送レートになるので使う可能性があるなら全部ダウンロードしておいても良いかもしれません。

*3:vramの設定を入れておかないと、ゲストOSの画面をfull screenにした時に文句を言われます。

コンパイラ製品のコミュニティエディション

MSがVisual StudioのComunity editionをリリースしてはや3年(くらいだっけ?)が経ちますが、同じようなノリでIntelとPGIもCommunity editionを出してたようです。*1


MSのも合わせてとりあえずリンクを置いときます。
www.visualstudio.com

Qualify for Free Software | Intel® Software

https://www.softek.co.jp/SPG/Pgi/pgi_community.html:www.softek.co.jp


3社とも通常の商用版からサポート等を無くしたもののようですが、それぞれ微妙に条件や動作環境が違っていて

MS
Windows版のみ、学生、個人、非営利団体、中小企業のみ利用可
Intel
Windows/Linux/Mac版のみ、学生、教員、OSS貢献者のみ利用可(ただしOSS貢献者はLinux版のみ)
PGI
Linux版/Mac版のみ(MAC版はGPGPU関連機能無し)、利用者の制限は無いがリリースから1年間のみ有効*2

となっています。

MSに関してはFortranコンパイラが無いのも一部の人には重要な違いかもしれません:p
あと、Intelに関してはコンパイラに付属しているいつものライブラリ(TBB/IPP/MKL)とData Analytics Acceralation Library*3は対象者の制限無しに公開されています。

Powerful and Award-winning Intel® Performance Libraries to Create Better, More Reliable, and Faster Software Applications


WindowsならVS community、LinuxMacならPGIコンパイラをインストールして、Intelのライブラリを呼び出すのが一番制約が少なそうですね。
PGIコンパイラに関しては並列デバッガ(PGDBG)*4も含まれてるようなので、これがうまく使えれば開発が楽になりますね。

*1:去年の秋ごろには見かけたような気がするけど、twitterでつぶやいただけでblogでは放置してたみたいで・・・

*2:Sharp Zaurusの開発環境を思いだした

*3:DAALと略すのかな?

*4:使ったことないけど・・・

Macの初期設定&備忘録

私事ながら、昨年末で5年ちょっと勤めた某社を退職し、自分で会社を立ち上げました。
というわけで、「あーこのネタをブログに書きたいけど会社の人にバレたら困るなー」みたいな制約が無くなりましたんで、今年からはもっと記事を書く頻度を上げていきたいと思います。*1

最初の記事ですが、この機に長年使い慣れたWindowsを捨ててマカーになったので自分用の備忘録として、初期設定などでやったことをまとめておきます。

HHKの設定変更

dipスイッチの1,2をonにしないとコマンドキーが送出されないので、これを変更しておく。
この変更を有効にするとFn+Tabがcaps lockとして機能するようになるので注意!

キーボードの設定変更

[システム環境設定] -> [キーボード] -> [キーボード] と進んで"キーのリピート"と"リピート入力認識までの時間"のスライダーを一番右へ設定する。
f:id:n_so5:20170111105532p:plain

マウスの設定変更

[システム環境設定] -> [マウス] と進んで"スクロールの方向: ナチュラル"のチェックボックスを外し"軌跡の速さ"と"スクロールの速さ"を調整
f:id:n_so5:20170111105548p:plain

dockの設定

ドックにもともと登録されているアプリはごみ箱へdrag&dropすれば削除できる。
逆に新規にアプリを登録する時は[Finder] -> [アプリケーション]と進むと一覧が表示されるので、そこからdrag&drop

コピペ

copy/cut/pasteはWindowsだとControl+C/X/Vだけど、macではCommand+C/X/Vが割り当てられている。
修飾キーが違うだけなんで、システム環境設定のキーボードのところでControlとCommandを入れ替えるというのがメジャーな方法らしいですが、これをやると全てのショートカットキーに影響が出るので、始めて使う機能(最初に書いたスクリーンショットとか)をググって調べながら使う時に支障がでそうです。
でも、Control+C/X/Vを有効にするだけだったら、こちらの方法でOK
d.hatena.ne.jp


うちの場合シンプルにこの3項目だけを書いています。

$ cat ~/Library/KeyBindings/DefaultKeyBinding.dict 
{
  "^c" = "copy:";
  "^v" = "paste:";
  "^x" = "cut:";
}

ディレクトリ名はKeyBinding**s**なのにファイル名はKeyBinding.dictなのに気付かずに1時間くらいはまってたので、ご注意を・・・orz

あと、この方法だとfirefox上では表示されているHTMLに対しては無効だけど、アドレスバーやtext area内のドキュメントに対しては有効という謎の状態になるようです。
ま、command+C/X/Vも有効なままなのでControlで反応すればCommandを使えば良いだけの話ですが。

==== 追記 ====

skkのインストール&設定

skkAquaSKKをこちらからダウンロードしてインストールします。
github.com
このままだと、ターミナル上でC-jを入力してもかなモードに切り替わらないので、こちらのコメントにあるようにkeymapにC-7/C-8/C-9あたりを追加しておきます。*2
github.com

あとhome brew, macvim, vagrant, virtualboxあたりもインストールしてますが単純に入れただけなので省いてます。

*1:年明けにこういうことを書くblogってのは大抵更新されないもんだけど・・・

*2:C-jを入力して効かなかった時に、右手の人差し指を適当に上の方に動かせばOKというキーアサインです

python3でtrelloに登録したカードを読み出す(その2)

前回作ったプログラムですが、実行に10秒ほどかかっていて、これならブラウザで複数プロジェクトのボードを全部開いてまわってもたいして効率が変わらない感じです。
おそらく遅い原因はボード一覧の取得->ボード毎にリスト一覧の取得->リスト毎にカード一覧の取得という一連の流れの中で、毎回O(N)相当のhttpリクエストを投げてるところだろうと思います。なんとか早くする方法が無いかと思って調べてたんですが、trelloのAPIリファレンスのページを見てると、こういう複数リクエストをまとめて投げるAPIがありました。
https://developers.trello.com/advanced-reference/batch
これを使えばこのプログラムのhttpリクエストは次の3回までに減らすことができます。

  1. ボード一覧の取得
  2. ボード内のリスト一覧の取得
  3. 所定のリスト(WIPとかToDoとか)内のカード一覧の取得

さっそく、前回てきとーに作ったTrelloClientクラスにbatch_fetch関数を追加してみます。

class TrelloClient:
    def __init__(self, api_key, token):
        self.api_key=api_key
        self.token=token
        self.base_url="https://api.trello.com/1"
    def fetch(self, category, api, target_id, option=""):
        url='{}/{}/{}/{}?key={}&token={}{}'.format(self.base_url,category,target_id,api,self.api_key,self.token,option)
        with  urllib.request.urlopen(url) as r:
            return json.loads(r.read().decode('utf-8'))
    def batch_fetch(self, category, api, target_ids, option=""):
        batch_url=""
        for target_id in target_ids:
            batch_url += "/{}/{}/{}/{},".format(category, id, api,option)
        batch_url=urllib.parse.quote(batch_url.rstrip(','))
        url="{}/batch/?urls={}&key={}&token={}".format(self.base_url, batch_url, self.api_key, self.token)
        with  urllib.request.urlopen(url) as r:
            return json.loads(r.read().decode('utf-8'))

これを使って全ボード内のリストの一覧を取得するとこんな感じのコードになります。

tc=TrelloClient(trello_api_key, trello_token)
boards=tc.fetch(category="member", api="boards", target_id="me", option="&filter=open&fields=name")
board_ids=[board['id'] for board in boards]
lists=tc.batch_fetch(category="boards", api="lists", target_ids=board_ids, option="?filter=open&fields=name&fields=idBoard")

今の時点のコードはこんな感じになってます。
n_so5 / TaskReporter / commit / 7197ec9bb6da — Bitbucket


新旧バージョンで実行時間を比較してみると

elapsed time for first version = 1.22e+01 sec
elapsed time for second version = 1.32e+00 sec

10倍早くなってますね。

python3でtrelloに登録したtask(=カード)を読み出す

googleカレンダーのお気に入りの機能のひとつに、「毎日指定した時間にその日の予定をメールで送ってくる」というのがあります。
気分的には、オフィスのエレベーターを降りて自席まで歩いている間に、クリップボードを持った秘書さんが付いてきて今日の予定を読み上げてくって感じ*1なんですが、
残念ながら我々エンジニアはカレンダーに入っているスケジュール済タスクだけをチェックしていると、色々と破綻します。

私の場合は、カレンダーの他にプロジェクト毎の課題管理のためにtrelloを使っていて案件毎に個別のボードにカンバン方式でタスクを登録しています。
ところが、trelloでボードをまたいでカードを見ようとすると自分にアサイン済のカード一覧を見るしかないので、BacklogからTodoへ(もしくはWIPへ)カードを移動させては自分へアサインし、Doneリストへ移動させてはアサインを外すという面倒なことをやっていました。
しばらくはこの方式で頑張ってたんですが、割り込みタスクのカードを作ったりすると徐々に破綻していって、今となっては自分にアサインされたカードの一覧を見ても入っていないタスクの方が多い有様です。

というわけで、一念発起して自分の担当案件のうち、作業中のタスクとToDo項目をtrelloから取得して表示するプログラムを作ってみました。

基本方針

  • python3で作成
  • urllibで頑張る(requestは使わない)
  • 出力先はとりあえずコンソール

trelloのカードを取得する準備

trelloのカードを取得するためには、APIキーとTokenを用意する必要があります。
まずは、次のURLへアクセスします。
https://trello.com/app-key
一番上に「キー:」と書かれた下に文字列があるので、これをメモっておきます。
続いて、「Token:」と書かれたセクションに"Token"というリンクがあるので、ここをクリックするといつもの認証画面に遷移します。
f:id:n_so5:20160906212740p:plain
ここで許可とすると

You have granted access to your Trello information.

To complete the process, please give this token:

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

という形でトークンの文字列が表示されるので、最後の行の文字列をメモっておきます。
以降のスクリプトでは、鍵をtrello_api_keyという変数に、トークンをtrello_tokenという変数に保存している前提で書きます。

ボードの一覧を取得

ボードの一覧を取得するには、次のAPIを呼びます。
https://developers.trello.com/advanced-reference/member#get-1-members-idmember-or-username-boards

コードで書くとこんな感じになります。

import urllib.request
import json

boards=[]
with  urllib.request.urlopen("https://api.trello.com/1/members/me/boards?key={}&token={}&filter=open&fields=name".format(trello_api_key, trello_token)) as r:
    tmp=r.read().decode('utf-8')
    boards=json.loads(tmp)

optionとして渡している文字列のうち、filter=openはOpenなボードのみ取得することを、fields=nameはボードの名前とidのみを取得することを意味しています。
これで、boardsには各ボードのidと名前を格納した辞書のリストが入ります。

次に進む前に、trelloのAPIを叩いて返ってきたjsonpythonのオブジェクトに変換して返すところまでをクラスにしておきましょう。

class TrelloClient:
    def __init__(self, api_key, token):
        self.api_key=api_key
        self.token=token
        self.base_url="https://api.trello.com/1"
    def fetch(self, category, api, target_id, option=""):
        url='{}/{}/{}/{}?key={}&token={}{}'.format(self.base_url,category,target_id,api,self.api_key,self.token,option)
        with  urllib.request.urlopen(url) as r:
            return json.loads(r.read().decode('utf-8'))

tc=TrelloClient(trello_api_key, trello_token)
boards=tc.fetch(category="member", api="boards", target_id="me", option="&filter=open&fields=name")

Taskの取得

ここまででボードのID(と名前)の一覧が取得できたので、次は各ボードに対してこちらのAPIを使ってリストの一覧を取得します。
https://developers.trello.com/advanced-reference/board#get-1-boards-board-id-lists
この時オプション引数のcardsとcard_fieldsを使うと、各リストに含まれるカードの一覧も取得できるので、これを使ってまとめてボード内のカードを取得します。ただし、この方法で取得すると全てのリストに入っているカードが返ってきてるので、TodoかWIPのリストに入っているカードだけを後から抽出する必要があります。
コードはこんな感じになります。(前のコードの続きです。)

todo={}
wip={}
for board in boards:
    lists=tc.fetch(category="boards", target_id=board["id"], api="lists", option="&filter=open&fields=name&cards=open&card_fields=name")
    for list in lists:
        if len(list['cards']) > 0:
            if list["name"] in ("ToDo", "todo", "Todo", "To do", "to do"):
                    todo[board["name"]]=list['cards']
            if list["name"] in ("WIP", "W.I.P.", "W.I.P", "Doing", "doing"):
                    wip[board["name"]]=list['cards']

リスト名の表記ゆれを考慮して一応それっぽい名前のものは全部対象のリストとみなすようにしてあります。

出力

こんな感じで取得したTodoとWIPのカード名を順にprintしていきます。

print("現在作業中のタスク")
for project, tasks in wip.items():
    print(project,":")
    for task in tasks:
        print("  -",task['name'])
    print("")

print("Todo項目")
for project, tasks in todo.items():
    print(project,":")
    for task in tasks:
        print("  -",task['name'])
    print("")

おまけ

このコードでは、ボード内の全カードを取得してから、不要な(対象外のリストに入っている)カードの除いていますが、trello APIで同時に取得できるアイテムの上限は1000なので1000以上のカードが入っているボードがあると全部のtaskを拾うことができません。こういう状況が起き得る場合は、ボード内のリストを取得する時に以下のように一旦リスト名の一覧を取得してから、必要なリストのカードを改めて取得する必要があります。

for board in boards:
    lists=tc.fetch(category="boards", target_id=board["id"], api="lists", option="&filter=open&fields=name)
    for list in lists:
        cards=tc.fetch(category="lists", target_id=list["id"], api="cards", option="&filter=open&fields=name")

私の環境だと、こっちの方がだいたい倍くらい遅かったんですが、もともと6~7秒で終わっていたのが10秒程度に伸びるくらいの感覚なので今のところこっちを使っています。

*1:洋画とかでよくやってるイメージ

pythonのwebbrowserモジュール

2年ほど前に、「へび年だからpythonの勉強でもするか」とかいう冗談みたいな理由でpythonを使い始めたんですが、今日初めてこんな素敵なモジュールがあることを知りました。

21.1. webbrowser — 便利なウェブブラウザコントローラー — Python 3.5.2 ドキュメント

このモジュール、名前が示すとおりの挙動で、URLを受け取ると標準のブラウザで開くというものです。

うちの環境だと、コマンドプロンプトから

> python -m webbrowser -t "http://www.python.org"

とやると、firefoxが立ち上がって(あるいは、新しいタブを開いて)python.orgのトップページを表示してくれます。







じゃ、cygwinでやるとどうなるかというと
f:id:n_so5:20160711163329p:plain
とりあえず、テキストブラウザが立ち上がりました。Bとか反応しないのでw3mじゃないのは確かだけど、このソフト何かなーと思いながら、qを押すと
f:id:n_so5:20160711164003p:plain
linksだったようです。
Links - Wikipedia


これは、cygwinのデフォルトブラウザがlinksになっているというわけじゃなくて、単にwebbrowserモジュールが持っているブラウザリストの中から、探していって見つかったものを呼んでるだけでしょうかね?


しかし、これでスクリプトからブラウザを開かせたりできるので大変便利そうです。
#アプリ連携の認証とか使える・・・?