Python」タグアーカイブ

subprocess run Popen

そういえば最近このブログは subprocess.Popen を使っているけど。
subprocess.run で全部まかなえるようになったんじゃなかったっけ?
Popen を使う理由は何だろう。

subprocessでPythonからLinuxコマンド実行

あぁ戻り値を得ないならば非同期実行になるってことね。
しかしなんともなサンプルコードだ、多分 Windows なんだろうけど。
UNIX 系ならこんなに単純なサンプルコードにできる。

#!/usr/bin/env python3

import subprocess

subprocess.Popen(['sh', '-c', 'sleep 3; echo First'])
subprocess.Popen(['sh', '-c', 'echo Second'])

print('__done__')

__done__ が一番最初に表示されるね、なるほど。
ただし with as を使うと戻り値を使うのと同様になるので順番どおりになる。

#!/usr/bin/env python3

import subprocess

with subprocess.Popen(['sh', '-c', 'sleep 3; echo First']) as p:
    pass
with subprocess.Popen(['sh', '-c', 'echo Second']) as q:
    pass

print('__done__')

この特性を上手く利用すれば色々便利になりそう。

subprocess readline loop

sftp を subprocess で関連は色々詰まって全然進まない。
特に stdout.readline は検索すると同じ事で詰まっている人ばかり見つかるってどうよ。
そうです、readline でループすると値が戻らず止まってしまうんです。
俺だけじゃなかった!なんて安心してもしょーがないんですけど。

python – catching stdout in realtime from subprocess – Stack Overflow

上記で上手くいっている人と駄目な人がいるみたいだけーが。
exe ってことは Windows なら問題ないってことなのかも、知らんけど。

Pythonでサブプロセスと対話する – 西尾泰和のはてなダイアリー

上記でやっとなんとかなった。
サンプルコード、bash のエミュレーター。

#!/usr/bin/env python3

import sys, subprocess, os

with subprocess.Popen(['/bin/bash'], encoding='UTF-8', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as p:
    while True:
        try:
            s = input('test > ')
        except EOFError:
            # Ctrl+D
            break
        p.stdin.write(f'{s}\n')
        p.stdin.flush()
        if s == '':
            continue
        if s == 'exit':
            break
        r = os.read(p.stdout.fileno(), 1024)
        sys.stdout.write(r.decode())
        sys.stdout.flush()
        # not UNIX ?
        #for line in iter(p.stdout.readline, b''):
        #    print(line.rstrip())

print('__done__')

os.read はファイルオブジェクトに使わないでって書いているけど動くようだ。
os — 雑多なオペレーティングシステムインタフェース ? Python 3.8.0 ドキュメント
ls の出力が改行されてしまう理由は解らない。
subprocess ごときにこんなに苦戦するとは思わなかったぞ。

subprocess sftp

sftp コマンドをラッピングしてアプリを自作するのもアリかも。
と前回書いたし自分で作ろうかなって。
Python なら subprocess であっさり作れそう。
後は PyObjC あたりで GUI を作ればいい。

まず問題なのがパスワード入力をどうするかってこと。
すぐに見つかったけど sshpass コマンドを使えば簡単にできるようだ。
Fedora には最初からあるけど macOS には無いんだなぁ。
まあいい後回し、今回は Fedora から接続で試す。

次は接続されるのを待つ必要があるな。

Python の subprocess – Qiita

この一番下みたいに開始の出力を得ればなんとかなりそう。
色々試したけど Connected to … は stderr 出力だ、なんだそれ。

Pythonでデッドロックを回避しながらサブプロセスの標準出力を1行ずつ読み込む – 物理の駅 by onsanai

デッドロックしまくったけどコレをみつけてなんとかなった。
色々遠回りしたけどなんとかなったコード。

#!/usr/bin/env python3

import shlex, subprocess

args = shlex.split('sshpass -p PASSWORD sftp USERNAME@HOSTNAME')

with subprocess.Popen(args, encoding='UTF-8', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as p:
    # wait Connect
    while True:
        line = p.stdout.readline()
        print(line)
        if 'Connected' in line:
            break
    # Start
    s = input('test > ')
    outs, errs = p.communicate(input=s, timeout=15)
    print(outs)

communicate ではプロセスが終わってしまうんだよな。
bye を送るまで while ループさせる所で今つまっている。

Paramiko 使えってのは無しにして、それじゃつまらないし勉強にもならない。
外部モジュールで満足する人はフリーソフトのインストールで満足しちゃう人だと思う。

PHP Imagick

さて PHP をやるといっても言語仕様なんてすぐに理解できる。
筆者はすぐ忘れる人なのでまたチップスページを作る、はいいとして。
PHP で何をやるかだ、とりあえず画像のリサイズだな。

PHPで画像をリサイズしよう!表示・保存方法もわかる | 侍エンジニア塾ブログ(Samurai Blog) – プログラミング入門者向けサイト

GD は定番として Imagick ってココ(さくら)で使えるのかな?
手持ちパソコン内だけで可能なのでは意味がないし。
と思ったけれど、どちらも問題なく使えるようだ。

【さくらのレンタルサーバ】基本仕様 ? さくらのサポート情報

ところで Fedora 自体は PHP をインストールしただけでは両方使えない。
てなわけで dnf する。

sudo dnf install php-gd php-pecl-imagick

httpd を通すのが面倒だからスクリプトで直接試す。
Linux はコレができるから楽なんだよね。

#!/usr/bin/env php

<?php

    // php-gd
    [$width, $hight] = getimagesize('test.jpg');
    $baseImage = imagecreatefromjpeg('test.jpg');
    $image = imagecreatetruecolor(100, 100);
    imagecopyresampled($image, $baseImage, 0, 0, 0, 0, 100, 100, $width, $hight);
    imagejpeg($image , 'out_01.jpg');

    // php-pecl-imagick
    $image2 = new Imagick('test.jpg');
    $image2->thumbnailImage(100, 0); // Segmentation fault...
    $image2->writeImage('out_02.jpg');
    $image2->clear();

?>

Imagick::thumbnailImage でセグメンテーション違反になってしまうヤン。
縮小画像は問題なく作成されるけど。
下記のように起動すればこのエラーは出なくなる、けどソレでいいのか?

env MAGICK_THREAD_LIMIT=1 php test.php

おまけ、cairo も使えるんだね。
PHP: Cairo – Manual
94. PHPからCairoを使う | 日経 xTECH(クロステック)

dnf で見つからないし必要性もあまり感じないので無視するけど。
せっかくなのでリンク先コードを Python3 で書き直ししてみた。
create なんてメソッドは無いのでこんなふうに。

#!/usr/bin/env python3

import cairo

surface = cairo.PDFSurface('sample.pdf', 605.0, 855.0)
cr = cairo.Context(surface)

cr.set_source_rgb (0.0, 0.0, 1.0)

cr.move_to(150, 150)
cr.select_font_face('Monospace', cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
cr.set_font_size(72)
cr.show_text('日本語OK!')
cr.show_page()

# 破棄はガベージコレクション

Linux てか GNOME って本当にプログラミングは楽チンだよね。

f-string

PEP 498 — Literal String Interpolation | Python.org

f-string なんてものが Python 3.6 から使えるのか。

#!/usr/bin/env python3

suzuki = 'スズキ'

# Python2 互換
print('%sのバイクはカッコイイ' % suzuki)
# Python3 format
print('{0}はスクーターもカッコイイ'.format(suzuki))
# f-string (3.6 or lator)
print(f'{suzuki}は自動車もカッコイイ')

# raw f-string
lf = '元からある改行はダメだけど\n'
print(fr'{lf}この \n は改行されない')

# docstring
doc = 'ヒアドキュメント'
print(f'''これなら ' も " も普通に使える
まるで{doc}だね''')

# ゼロ詰め
for n in range(3):
    print(f'{n:#03d}')

なるほど。

当然だけど f-string が一番短く書ける、かつ理解しやすい。
ゼロ詰めが可能なので js のテンプレートリテラルより便利。
今後 Python はコレでいこう。

vscode だとヘンテコな色分けをしてくれます。
てか f’ と打ったら閉じクォートを勝手に補完するのをヤメてくれ!
閉じクォート補完設定は OFF にしているのに、別設定なのかよ。
本当に余計なことばかりするクソエディタだな。

私的には $ 記号が欲しかった、sh, php, js 互換になるし。