Python学習【365日チャレンジ!】100日目のマスターU(@Udemy11)です。
なんだかんだいって、100日継続することができてめっちゃ嬉しいマスターUです。
100って数字はやっぱり興奮しちゃいますよね!
とはいえ、まだ目標達成まであと265日あるので、しっかりと気を引き締めてPython学習を継続していきたいと思います。
それではさっそく今日もPython学習をはじめましょう!
昨日の復習
昨日は、tempファイルの取り扱いについて学習しました。
一時ファイルであるtemporary
ファイルですが、【I/Oバッファ】に書き込まれるものと、実際にtemporary
ファイルやフォルダに書き込まれて、作業が終了したら削除されるものがありました。
import tempfile
with tempfile.TemporaryFile(mode='w+') as temp:
temp.write('What is your name?')
temp.seek(0)
print(temp.read())
with tempfile.NamedTemporaryFile() as n_temp:
with open(n_temp.name, 'w+') as f:
f.write('How are you?')
f.seek(0)
print(f.read())
with tempfile.TemporaryDirectory() as temp_d:
print(temp_d)
出力結果
What is your name?
How are you?
/private/var/mobile/Containers/Data/Application/CCBA549E-E8FE-4616-A553-00250CF9575D/tmp/tmpqme27m38
3行目のTemporaryFile
メソッドは、情報を【I/Oバッファ】に記録して削除します。
8行目のNamedTemporaryFile
メソッドと14行目のNamedTemporaryFile
は、tmp
フォルダにファイルやフォルダを作成して、作業終了後に削除します。
NamedTemporaryFile
には、引数delete
が用意されていて、デフォルトがTrue
ですが、False
を指定すれば、作業終了後もファイルを削除せずに残すことができました。
フォルダも同様に、mkdtemp
メソッドを使えば、自動的に削除せずに残すことができますが、自分で作ったフォルダとその中身を削除する必要がありました。
詳しくは昨日の記事を参照してください。
それでは本日の学習をすすめましょう!
Pythonistaでsubprocess
subprocess
モジュールは、Pythonファイルからコマンドを実行できる標準ライブラリです。
Macならターミナル、WindowsならコマンドプロンプトをPythonファイルから実行できて、少し前に学習したファイル操作のos
モジュールの拡張版みたいな感じがします。
MacのターミナルとWindowsのコマンドはコードが違いますが、Appleが大好きなので、Macで使うターミナル用のコマンドですすめていきます。
いつものように、Pythonistaでコードを書いているときにこんな考えが浮かんできました。
iPhoneってターミナル使えないから、subprocess
って、Pythonistaだと使えないんじゃないの?
といっても実行してみないことにはわからないので、とりあえずPythonistaで下記のコードを実行してみました。
import subprocess
subprocess.run(['ls'])
結果はやはり、エラーが返されちゃうんですよね。
パーミッションエラーとのことなので、読み込みが禁止されているみたいですが、StaShでls
コマンドを使えば表示されるんです。
Pythonistaではsubprocess.run()
が使えないようなので、別の方法でsubprocess
メソッドを実行してみます。
Pycharmでsubprocess
Pythonistaではsubprocess
メソッドが実行できないことがわかったので、Pycharmでsubprocess.run()
を実行してみます。
import subprocess
subprocess.run(['ls'])
出力結果
Keyword
box
design
lesson.py
lesson_package
session6
test.tar.gz
test.txt
test.zip
subprocess
モジュールは、run
関数を使って、リストでコマンドを指定すれば、ターミナルでコマンドを実行した場合と同じ結果が表示されます。
ls
コマンドは、現在の階層にあるファイルやフォルダを表示してくれるコマンドです。
ターミナルの場合は、半角スペースに続けてオプションを指定しますが、subprocess.run()
の場合は、リストの'ls'
のあと、,(カンマ)+半角スペース
に続けてオプションを指定します。
import subprocess
subprocess.run(['ls', '-al'])
出力結果
total 32
drwxr-xr-x 13 bigmacpro staff 416 May 6 18:04 .
drwxr-xr-x 4 bigmacpro staff 128 Feb 16 20:23 ..
drwxr-xr-x 8 bigmacpro staff 256 May 6 18:03 .idea
drwxr-xr-x 4 bigmacpro staff 128 Apr 26 14:24 Keyword
drwxr-xr-x 5 bigmacpro staff 160 Apr 11 00:08 box
drwxr-xr-x 3 bigmacpro staff 96 Apr 29 21:33 design
-rw-r--r-- 1 bigmacpro staff 49 May 6 18:04 lesson.py
drwxr-xr-x 8 bigmacpro staff 256 Apr 4 16:27 lesson_package
drwxr-xr-x 8 bigmacpro staff 256 Apr 29 21:34 session6
-rw-r--r-- 1 bigmacpro staff 220 May 3 20:36 test.tar.gz
-rw-r--r-- 1 bigmacpro staff 9 May 6 17:57 test.txt
-rw-r--r-- 1 bigmacpro staff 488 May 3 21:34 test.zip
-al
は、ファイルの詳細を表示するオプションです。
表示される内容は、
- ファイルの種類とパーミッション(許可属性)
- ハードリンク数
- 所有者
- グループ名
- ファイルサイズ
- タイムスタンプ
- ファイル名
となっていて、こういうコマンドを使って何をするのかは全く想像がつかないのですが、ちょっとだけプログラマー気分になれちゃうんですよね。
非推奨のos.system
古いPythonでは、os.system()
を使ってコマンドを実行していましたが、Python3.5からsubprocess
<メソッドにrun()
関数が追加され、コマンドを扱えるようになりました。
今でもos.system()
は使用可能ですが、非推奨となっています。
一応、使い方を紹介しておきます。
import os
os.system('ls')
出力結果
Keyword
box
design
lesson.py
lesson_package
session6
test.tar.gz
test.txt
test.zip
リストではなく、直接引数に'ls'
を指定することでコマンドを実行できます。
あくまで参考ということで、古いプログラミングのコードにはos.system()
を使っているものもあると思うので、見かけたらわかる程度に憶えておきましょう。
shell=Trueは使わない
以下の内容は、参考として憶えて置く程度でいいのですが、subprocess
メソッドは、ターミナルのコマンドをそのまま扱えるようにできます。
引数shell
がデフォルトでは、False
になっているのですが、shell=True
とすれば、リストにして,(カンマ)
で区切らなくてもターミナルのコマンドをそのまま実行することができます。
import subprocess
subprocess.run('ls -al | grep test', shell=True)
shell=True
にすることで、シェルに処理をさせることができ、このコマンドの場合は、フォルダ内のファイルやフォルダの中からtest
が含まれたものを検索するという処理をシェルにさせています。
os.system()
の場合は、引数を指定しなくてもデフォルトで同じことができますが、セキュリティーの関係で、この使い方はおすすめできないということです。
コマンドのことはきちんと理解していませんが、シェルに処理をさせると|(パイプ)
を付け加えて追加の処理をさせることができるため、意図しない処理や悪意を持ってディレクトリを丸ごと削除してしまうこともできるらしいです。
例えば、shell=True
にしたsubprocess.run()
関数に,
コマンドを入れた変数を代入する形でコマンドを実行する場合、何かのきっかけで| rm -rf *
(書き込み許可がなくてもディレクトリ以下のすべてのファイルやフォルダを削除するというコマンド)を追加してしまうと、ディレクトリがすべて削除されて大変なことになってしまいます。
cmd = 'コマンド | rm -rf *'
subprocess.run(cmd, shell=True)
どんなときに、こんな問題が起こるのかはわかりませんが、このようなリスクがあるということで、Pythonファイルからのコマンド実行は、os.system
からsubprocess.run()
に変更されたのだと思います。
すべてを理解できない
100日継続してPythonを学習してきましたので、ある程度はPythonのことがわかってきたつもりですが、まだまだ5%もわかっていないような感じがします。
何気なくPython公式ドキュメントをのぞいてみると、知らないことだらけで、ほんとにほんの一部だけしか学習できていない現実を思い知らされてしまいます。
ほんと、Pythonを開発した人の頭の中ってどうなってるんでしょうね?
とはいえ、できることといえば、一つ一つわからないことを実践しつつ、身につけていくしかないので、これからも小さな積み重ねをコツコツと積み上げていこうと思います。
それでは明日もGood Python!