Python 学習メモ

Tech
Table of Contents
  1. 文字列操作
  2. 文字列結合
  3. インデックスとスライス
  4. 文字列のメソッド
  5. 条件文のかつ、または
  6. 何も入ってないとき、Noneで表す、None の判定は is を使う
  7. while else、for else は、 break したら else が呼ばれない。
  8. for 文で break
  9. continue だと else は呼ばれる
  10. range
  11. ループでインデックスが欲しいとき、enumerate 関数を利用
  12. zip関数 まとめて配列を回してくれる
  13. 辞書(ディクショナリー)をfor文で回す
  14. デフォルト引数にリスト、ディクショナリを指定すると、参照先が同じでバグの元になる
    1. 引数がないときはは None になるので、このように初期化してやる
  15. 位置引数のタプル化
  16. 位置引数のタプル化でタプルを渡すとき
  17. ** で引数の辞書化(ディクショナリー型で受け取る)
  18. 引数の辞書(ディクショナリー型)に辞書(ディクショナリー型)を展開して渡す
  19. 関数内関数
  20. クロージャー
  21. デコレーター
    1. デコレーターを使う前
    2. デコレーターを使った後
  22. ラムダ
  23. ジェネレーター
  24. ジェネレーター 2
  25. リスト内包表記
  26. 辞書内包表記
  27. 集合内包表記 (Setの内包表記)
  28. ジェネレーター内包表記
  29. 名前空間とスコープ
  30. 例外処理
  31. 独自例外処理
  32. import と AS
  33. アスタリスクのインポート
  34. import Error の使い所
  35. setup.py でパッケージ化
    1. PyCharm
    2. コマンド
  36. 組み込み関数 sorted
  37. 標準ライブラリ defaultdict
  38. ライブラリの場所、Sysパスの確認
  39. クラスの定義
  40. クラスの初期化(コンストラクタ)とクラス変数
  41. デストラクター
  42. 継承
  43. オーバーライドとsuperによる親のメソッド呼び出し
  44. プロパティーを使った属性の設定
    1. プロパティーは、先頭に_を付ける。
    2. getter には @property を付ける
    3. setter には getter のメソッド名をアノテーションで記載する。
    4. プロパティー__を付けると private なプロパティになる。
  45. 抽象クラス
  46. 多重継承
    1. 先に継承されたクラスのメソッドが優先される件
  47. クラス変数
  48. クラスメソッドとスタティックメソッド
  49. 特殊メソッド
  50. ファイルの作成(書き込み)
  51. with ステートメントでファイルをopenする。
  52. ファイルの読み込み
  53. seekを使って(カーソルを)移動
  54. 書き込み、読み込みモード
  55. テンプレート
  56. CSVファイルの書き込み、読み込み
  57. ファイルの操作
  58. tarファイル
  59. zipファイル
  60. tempfile
  61. subprocess でコマンドを実行する
  62. datetime

文字列操作

print(r'C:\name\name')  # => C:\name\name   raw文字列でエスケープシーケンスを無視(無効化)
# 改行する
print("line1\nline2\nline3")
# 改行あり
print("""
line1
line2
line3
""")
# 最初と最後の改行なし
print("""\
line1
line2
line3\
""")

文字列結合

print('Hi.' * 3 + 'Mike.')  # Hi.Hi.Hi.Mike.
print('aaa' + 'bbb')        # => aaabbb
print('aaa''bbb')           # => aaabbb
print('aaa'
      'bbb')                # => aaabbb

インデックスとスライス

word = 'python'
print(word[0])    # => p
print(word[1])    # => y
print(word[-1])   # => n
print(word[0:2])  # => py
print(word[:2])   # => py
print(word[2:5])  # => tho
print(word[2:])   # => thon
print('j' + word[1:])   # => jython

文字列のメソッド

s = 'My name is Mike. Hi Mike.'
print(s)                      # => My name is Mike. Hi Mike.
is_start = s.startswith('My')
print(is_start)               # => True

print(s.find('Mike'))   # => 11  最初から探して11番目にMikeあり
print(s.rfind('Mike'))  # => 20  最後のを探すと20番目にMikeあり
print(s.count('Mike'))  # => 2   Mikeが2つ存在する。
print(s.capitalize())   # => My name is mike. hi mike. 最初だけ大文字
print(s.title())        # => My Name Is Mike. Hi Mike. 単語の先頭が全てが大文字
print(s.upper())        # => MY NAME IS MIKE. HI MIKE. 全て大文字
print(s.lower())        # => my name is mike. hi mike. 全て小文字
print(s.replace('Mike', 'Nancy'))  # => My name is Nancy. Hi Nancy. 「Mike」を「Nancy」に置換

条件文のかつ、または

andor を利用する。

何も入ってないとき、Noneで表す、None の判定は is を使う

is_empty = None
if is_empty is None:
    print('Hello')

if is_empty is not None:
    print('Hello')

while else、for else は、 break したら else が呼ばれない。

count = 0
while count < 5:
    if count == 4:
        break
    print(count)
    count += 1
else:
    print('done') # breakしてるから呼ばれない

for 文で break

for fruit in ['apple', 'banana', 'orange']:
    if fruit == 'banana' :
        break
    print(fruit)
else:
    print('I ate all!')  # breakしてるから呼ばれない

continue だと else は呼ばれる

for fruit in ['apple', 'banana', 'orange']:
    if fruit == 'banana':
        continue
    print(fruit)
else:
    print('I ate all!')   # continue だと呼ばれる。

range

# 10回ループ
for i in range(10):
    print(i)
# => 0
# => 1
# => 2
# => 3
# => 4
# => 5
# => 6
# => 7
# => 8
# => 9
# 10回ループするけど5から
for i in range(5, 10):
    print(i)
# => 5
# => 6
# => 7
# => 8
# => 9
# 2から10まで3こ飛ばし
for i in range(2, 10, 3):
    print(i)
# => 2
# => 5
# => 8
# 変数はしようしないとき
for _ in range(10):
    print('hello')

ループでインデックスが欲しいとき、enumerate 関数を利用

for i, fruit in enumerate(['apple', 'banana', 'orange']):
    print(i, fruit)
# => 0 apple
# => 1 banana
# => 2 orange

zip関数 まとめて配列を回してくれる

days = ['Mon', 'Tue', 'Wen']
fruits = ['apple', 'banana', 'orange']
drinks = ['coffee', 'tea', 'beer']
for day, fruit, drink in zip(days, fruits, drinks):
    print(day, fruit, drink)

# => Mon apple coffee
# => Tue banana tea
# => Wen orange beer

辞書(ディクショナリー)をfor文で回す

d = {'x': 100, 'y': 200}

print(d.items())
# => dict_items([('x', 100), ('y', 200)])  ※タプルの配列になる

for k, v in d.items():
    print(k, ':', v)

# => x: 100
# => y: 200

デフォルト引数にリスト、ディクショナリを指定すると、参照先が同じでバグの元になる

def test_func(x, l=[]):
    l.append(x)
    return l

r = test_func(100)
print(r)  # => [100]

r = test_func(100) # [100, 100]
print(r)

引数がないときはは None になるので、このように初期化してやる

def test_func(x, l=None):
    if l is None:
        l = []
    l.append(x)
    return l

r = test_func(100)
print(r)  # => [100]

r = test_func(100) # [100, 100]
print(r)

位置引数のタプル化

def say_something(*args):
    print(args)  # => ('Hi!', 'Mike', 'Nance') タプルで取得される

say_something('Hi!', 'Mike', 'Nance')

位置引数のタプル化でタプルを渡すとき

def say_something(*args):
    print(args)  # => ('Hi!', 'Mike', 'Nance') タプルで取得される

t = ('Hi!', 'Mike', 'Nance')
say_something(t)   # =>  (('Hi!', 'Mike', 'Nance'),)  タブルがタブルに入ってる。
say_something(*t)  # => ('Hi!', 'Mike', 'Nance')   *で展開して渡す

** で引数の辞書化(ディクショナリー型で受け取る)

def menu(**kwargs):
    print(kwargs) # => {'entree': 'beef', 'drink': 'coffee'}

menu(entree='beef', drink='coffee')

引数の辞書(ディクショナリー型)に辞書(ディクショナリー型)を展開して渡す

def menu(**kwargs):
    print(kwargs) # => {'entree': 'beef', 'drink': 'coffee', 'dessert': 'ice'}
d = {
    'entree':'beef',
    'drink':'coffee',
    'dessert':'ice'
}
menu(**d)

関数内関数

def outer(a, b):
    def plus(c, d):
        return c + d

    r = plus(a, b)
    print(r)

outer(1, 2)

クロージャー

def outer(a, b):
    def inner():
        return a + b

    return inner

f = outer(1, 2)  # まだ実行されない
r = f()                # 実行する
print(r)               # => 3

デコレーター

デコレーターを使う前

def print_info(func):
    def wrapper(*args, ** kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

def add_num(a, b):
    return a + b

f = print_info(add_num)
r = f(10, 20)
print(r)

デコレーターを使った後

def print_info(func):
    def wrapper(*args, ** kwargs):
        print('start')
        result = func(*args, **kwargs)
        print('end')
        return result
    return wrapper

@print_info
def add_num(a, b):
    return a + b

f = add_num(10, 20)
print(f)

ラムダ

l = ['Mon', 'tue', 'Wed', 'Thu', 'fri', 'sat', 'Sun']
def change_words(words, func):
    for word in words:
        print(func(word))

def sample_func(word):
    return word.capitalize()

# 通常
change_words(l, sample_func)

# ラムダで sample_func を書き換えた実装
change_words(l, lambda word: word.capitalize())

ジェネレーター

def greeting():
    yield 'Good morning'
    yield 'Good afternoon'
    yield 'Good night'

# for g in greeting():
#     print(g)

g = greeting()
print(next(g))  # Good morning
print('---')
print(next(g))  # Good afternoon
print('---')
print(next(g))  # Good night

ジェネレーター 2

def counter(num=10):
    for _ in range(num):
        yield 'run'

c = counter()

print(next(c))
print(next(c))
print(next(c))
print(next(c))

リスト内包表記

t = (1, 2, 3, 4, 5,)

r = []
for i in t:
    if i % 2 == 0:
        r.append(i)
print(r)

r = [i for i in t if i % 2 == 0]
print(r)

辞書内包表記

w = ['mon', 'tue', 'wed']
f = ['coffee', 'milk', 'water']

d = {}
for x, y in zip(w, f):
    d[x] = y
print(d) # => {'mon': 'coffee', 'tue': 'milk', 'wed': 'water'}

d = {x: y for x, y in zip(w, f)}
print(d) # => {'mon': 'coffee', 'tue': 'milk', 'wed': 'water'}

集合内包表記 (Setの内包表記)

s = set()
for i in range(10):
    if i % 2 == 0:
        s.add(i)
print(s) # => {0, 2, 4, 6, 8}

s = {i for i in range(10) if i % 2 == 0}
print(s) # => {0, 2, 4, 6, 8}

ジェネレーター内包表記

def g():
    for i in range(10):
        yield i

g = g()
print(next(g))  # => 0
print(next(g))  # => 1
print(next(g))  # => 2

g = (i for i in range(10))
print(next(g))  # => 0
print(next(g))  # => 1
print(next(g))  # => 2

g = (i for i in range(10))
print(type(g))  # => <class 'generator'>

# タプルの場合は tuple をつける
g = tuple(i for i in range(10))
print(type(g))  # => <class 'tuple'>

名前空間とスコープ

animal = 'cat'
def f():
    animal = 'dog'
    print(globals()['animal'])
    print(locals()['animal'])

f()

print(globals())  # グローバルの
print(locals())   # グローバルのローカルはグローバルと同じ

例外処理

l = [1, 2, 3]
i = 5
# NameErrorにするための例
# del l

try:
    # IndexErrorにするため例
    l[i]
    # その他の Exception にするため
    # () + 1
except IndexError as ex:
    print("Don't worry: {}".format(ex))
except NameError as ex:
    print(ex)
except Exception as ex:
    print('other: {}', ex)
else:
    print('done')   # エラーがなくて成功したときだけ実行
finally:
    print('clean up')  # except がなくても必ず実行される

print("last")

独自例外処理

class UppercaseError(Exception):
    pass

def check():
    words = ["APPLE", "orange", "banana"]
    for word in words:
        if word.isupper():
            raise UppercaseError(word)

try:
    check()
except UppercaseError as ex:
    print("This is my fault. Go next")

import と AS

#基本的には②でインポート

# ①
# import lesson_package.utils

# ②
from lesson_package import utils

# ③
# from lesson_package.utils import say_twice

# ①
# r = lesson_package.utils.say_twice('hello')

# ②
r = utils.say_twice('hello')

# ③
# r = say_twice("hello")

print(r)
# インポートのASはあまり利用しないほうがよい
from lesson_package import utils as u

アスタリスクのインポート

アスタリスクのインポートには、init.py の all で使う関数、変数などを記載しないと使えない。

lesson_package/lesson.py

from lesson_package.talk import *

print(animal.hoge)

lesson_package/talk/init.py

__all__ = ['animal']

import Error の使い所

古いパッケージでエラーになったら新しいのを読み込むみたいなとき、ImportError が使える。

try:
    from lesson_package import utils
except ImportError:
    from lesson_package.tools import utils

utils.say_twice('word')

setup.py でパッケージ化

PyCharm

  1. Tools -> Create setup.py で入力する。
  2. setup.py が作成される。
    • setup.py の中で package の配列にパッケージが記載されている。
  3. Tools -> Run setup.py task… を押下する。
  4. sdist を選択する。
  5. dist フォルダに tar.gz のファイル(パッケージ)ができる
  6. *.egg-info ディレクトリにいろいろ README.md に記載したほうがいいドキュメントができている。

コマンド

  • コマンドで setup.py からパッケージを作成するコマンド
% python setup.py sdist

組み込み関数 sorted

ranking = {
    'B': 85,
    'A': 100,
    'C': 95,
}

# キーの昇順 アルファベット潤
print(sorted(ranking))  # =>  ['A', 'B', 'C']

# 値の昇順
print(sorted(ranking, key=ranking.get))  # =>  ['B', 'C', 'A']

# 値の降順
print(sorted(ranking, key=ranking.get, reverse=True))  # => ['A', 'C', 'B']

標準ライブラリ defaultdict

文字列から各文字の出現回数をカウントする処理で3パターンをの実装

s = "afaklcuslamdasfasfdasf"
d = {}
for c in s:
    if c not in d:
        d[c] = 0
    d[c] += 1
print(d)
# => {'a': 6, 'f': 4, 'k': 1, 'l': 2, 'c': 1, 'u': 1, 's': 4, 'm': 1, 'd': 2}

d = {}
for c in s:
    d.setdefault(c, 0)
    d[c] += 1
print(d)
# => {'a': 6, 'f': 4, 'k': 1, 'l': 2, 'c': 1, 'u': 1, 's': 4, 'm': 1, 'd': 2}

from collections import defaultdict
d = defaultdict(int)
for c in s:
    d[c] += 1

print(d)
# => defaultdict(<class 'int'>, {'a': 6, 'f': 4, 'k': 1, 'l': 2, 'c': 1, 'u': 1, 's': 4, 'm': 1, 'd': 2})

ライブラリの場所、Sysパスの確認

import termcolor  # サードパーティーのパッケージ
import sys

print(termcolor.__file__)
print(sys.path)

クラスの定義

  • python3 はクラスに object があってもなくてもOK、どれでもOK。Person(object):Person():Person:

クラスの初期化(コンストラクタ)とクラス変数

  • self は Java の this と同じ
  • クラスメソッドには self が引数につく
class Person(object):
    def __init__(self, name):
        self.name = name

    def say_something(self):
        print("I am {}. hello ".format(self.name))
        self.run(10)

    def run(self, num):
        print("run" * num)

person = Person("Mike")
person.say_something()

デストラクター

class Person(object):
    def __init__(self, name):
        self.name = name

    # 使わなくなったら実行される。
    def __del__(self):
        print("good bye")

person = Person("Mike")

# 明示的 __del__ を呼び出す場合
del person

継承

class Car(object):
    def run(self):
        print("run")

class ToyotaCar(Car):
    # 継承するだけでなにもしない
    pass

class TeslaCar(Car):

    def auto_run(self):
        print("auto run")

car = Car()
car.run()
print("-------------")
toyota_car = ToyotaCar()
toyota_car.run()
print("-------------")
tesla_car = TeslaCar()
tesla_car.run()
tesla_car.auto_run()

オーバーライドとsuperによる親のメソッド呼び出し

class Car(object):
    def __init__(self, model=None):
        self.model = model
    def run(self):
        print("run")

class ToyotaCar(Car):
    # オーバーライド
    def run(self):
        print("fast")

class TeslaCar(Car):

    def __init__(self, model='Model S', enable_auto_run=False):
        # ★superの__init__呼び出し
        super().__init__(model)
        self.enable_auto_run = enable_auto_run

    # ★オーバーライド
    def run(self):
        print("super fast")

    def auto_run(self):
        print("auto run")

car = Car()
car.run()
print("-------------")
toyota_car = ToyotaCar("Lexus")
print(toyota_car.model)
toyota_car.run()
print("-------------")
tesla_car = TeslaCar("Model S")
print(tesla_car.model)
print(tesla_car.enable_auto_run)
tesla_car.run()
tesla_car.auto_run()

プロパティーを使った属性の設定

プロパティーは、先頭に_を付ける。

def __init__(self, enable_auto_run=False):
    self._enable_auto_run = enable_auto_run

getter には @property を付ける

@property
def enable_auto_run(self):
    return self._enable_auto_run

setter には getter のメソッド名をアノテーションで記載する。

@enable_auto_run.setter
def enable_auto_run(self, is_enable):
    self._enable_auto_run = is_enable

プロパティー__を付けると private なプロパティになる。

self.__enable_auto_run = enable_auto_run

抽象クラス

  • abc ライブラリで継承を実装する。
  • 抽象メソッドには、@abc.abstractmethod を付ける
import abc
class Person(metaclass=abc.ABCMeta):
    def __init__(self, age=1):
        self.age = age
    @abc.abstractmethod
    def drive(selfs):
        pass

多重継承

先に継承されたクラスのメソッドが優先される件

class Person(object):
    def talk(self):
        print('talk')
    def run(self):
        print('person run')

class Car(object):
    def run(self):
        print('run')

class PersonCarRobot(Person, Car): # 先にPersonが継承されているので、Personクラスの run メソッドが優先される
    def fly(self):
        print('talk')

person_car_robot = PersonCarRobot()
person_car_robot.talk() # => talk
person_car_robot.run()  # => person run   ★先に継承されたクラスのメソッドが優先される
person_car_robot.fly()  # => talk

クラス変数

class Person(object):
    # クラス変数
    kind = 'human'
    def __init__(self, name):
        self.name = name
    def who_are_you(self):
        print(self.name, self.kind)

a = Person('A')
a.who_are_you()  # => A human

b = Person('B')
b.who_are_you()  # => B human

class T(object):
    # クラス変数で配列を宣言
    words = []
    def add_word(self, word):
        self.words.append(word)

c = T()
c.add_word('add 1')
c.add_word('add 2')

d = T()
d.add_word('add 3')
d.add_word('add 4')

print(c.words)  # => ['add 1', 'add 2', 'add 3', 'add 4']

クラスメソッドとスタティックメソッド

class Person(object):
    # クラス変数
    kind = 'human'
    def __init__(self):
        self.x = 100

    # クラスメソッド
    @classmethod
    def what_is_your_kind(cls):
        return cls.kind

    # スタティックメソッド、クラスの中になくてもOK
    @staticmethod
    def about():
        print('about human')

a = Person()
print(a)  # => <__main__.Person object at 0x100a8b2e0>
print(a.x) # => 100
print(a.kind) # => human
print(a.what_is_your_kind()) # => human
a.about()  # => about human

b = Person
print(b) # => <class '__main__.Person'>
print(a.x) # => エラー インスタンスを生成してない。
print(b.kind) # => human
print(b.what_is_your_kind()) # => human
b.about()  # => about human

特殊メソッド

class Word(object):
    def __init__(self, text):
        self.text = text
    def __str__(self):
        return 'Word!!!!!'
    def __len__(self):
        return len(self.text)
    def __add__(self, word):
        return self.text.lower() + word.text.lower()
    def __eq__(self, word):
        return self.text.lower() == word.text.lower()
w = Word('test')
print(w)       # => Word!!!!!
print(len(w))  # => 4

w2 = Word('####')
print(w + w2)  # => test####
print(w == w2)  # => false

w3 = Word('hoge')
w4 = Word('hoge')
print(id(w3))  # => 4347419520
print(id(w4))  # => 4347419424
print(w3 == w4)  # => True   ※ことなるオブジェクトだが __eq__ の実装でテキストが同じだと真にするよう実装しているためTrue

ファイルの作成(書き込み)

f = open("test.txt", "w")
f.write("Text\n") # => test.txt ファイルに書き込まれる
print("My", "name", "is", "Mike", file=f)  # => print でも test.txt ファイルに書き込まれる
f.close()

text.txtファイルの中身
Text
My name is Mike

with ステートメントでファイルをopenする。

with open("test.txt", "w") as f:
    f.write("Text\n") # => test.txt ファイルに書き込まれる
    #  with ステートメントで勝手にファイルをcloseしてくれる

ファイルの読み込み

s = """\
AAA
BBB
CCC
DDD
"""
# 書き込み
with open("test.txt", "w") as f:
    f.write(s)  # => test.txt ファイルに書き込まれる

# 読み込み
with open("test.txt", "r") as f:
    while True:
        # 1行ずつ読み込む
        line = f.readline()
        print(line, end="")

        # 2文字ずつ読み込む
        chunk = 2
        line = f.read(chunk)
        print(line)

        if not line:
            break

seekを使って(カーソルを)移動

s = """\
AAA
BBB
CCC
DDD
"""
# 書き込み
with open("test.txt", "w") as f:
    f.write(s)  # => test.txt ファイルに書き込まれる

# 読み込み
with open("test.txt", "r") as f:
    print(f.tell())   # => 0  今の場所(カーソル位置)を表示
    print(f.read(1))  # => A  1文字読み込む
    f.seek(5)         # 5番目に移動
    print(f.read(1))  # => B

書き込み、読み込みモード

s = """\
AAA
BBB
CCC
DDD
"""
# 書き込み w+ は書き込みをして、読み込み
with open("test.txt", "w+") as f:
    f.write(s)  # 新規にファイルが作成される
    f.seek(0)  # 先頭に移動する
    print(f.read())

# 書き込み r+ は読み込みをして、書き込み ※ファイルが存在しないとエラー
with open("test.txt", "r+") as f:
    print(f.read()) # ファイルを読み込む
    f.seek(0) # 先頭に移動する
    f.write(s)

テンプレート

import string

s = """\

Hi $name

$contents

Have a good day
"""

t = string.Template(s)
contents = t.substitute(name="Mike", contents="How are you?")
print(contents)

# 出力
---------
Hi Mike

How are you?

Have a good day
---------

CSVファイルの書き込み、読み込み

import csv
with open("test.csv", "w") as csv_file:
    fieldnames = ["Name", "Count"]
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({"Name": "A", "Count": 1 })
    writer.writerow({"Name": "B", "Count": 2})

with open("test.csv", "r") as csv_file:
    reader = csv.DictReader(csv_file)
    for row in reader:
        print(row["Name"], row["Count"])

ファイルの操作

import glob
import os
import pathlib
import shutil

print(os.path.exists("test.txt"))  # => True  ファイルの存在
print(os.path.isfile("test.txt"))  # => True  ファイルかチェック
print(os.path.isdir("venv"))  # => True ディレクトリかチェック

# ファイルの名前を変更
os.rename("test.txt", "renamed.txt")
# symlinkを貼る
os.symlink("renamed.txt", "test.txt")

os.mkdir("test_dir")  # ディレクトリを作成
os.rmdir("test_dir")  # ディレクトリを削除

pathlib.Path("empty.txt").touch() # 空ファイル生成
os.remove("empty.txt")  # 空ファイル生成

os.mkdir("test_dir")  # ディレクトリを作成
os.mkdir("test_dir/test_dir2")  # さらにディレクトリを作成
print(os.listdir("test_dir"))  # => ['test_dir2']  ディレクトリ確認

pathlib.Path("test_dir/test_dir2/empty.txt").touch()  #空ファイル作成
shutil.copy("test_dir/test_dir2/empty.txt", "test_dir/test_dir2/empty2.txt")
print(glob.glob("test_dir/test_dir2/*"))  # => ['test_dir/test_dir2/empty.txt']  ディレクトリのファイル一覧を表示
shutil.rmtree("test_dir")  # ディレクトリを再起的に削除
print(os.getcwd())  # 今のディレクトリの位置

tarファイル

import tarfile

# 圧縮
with tarfile.open("test.tar.gz", "w:gz") as tr:
    tr.add("test_dir")

# 展開
with tarfile.open("test.tar.gz", "r:gz") as tr:
    tr.extractall(path="test_tar")
    # 展開せずファイルを見る
    with tr.extractfile("test_dir/sub_dir/sub_test.txt") as f:
        print(f.read())

zipファイル

import glob
import zipfile

# 圧縮
with zipfile.ZipFile("test.zip", "w") as z:
    # z.write("test_dir")
    # z.write("test_dir/test.txt")
    for f in glob.glob("test_dir/**", recursive=True):
        print(f)
        z.write(f)

# 展開
with zipfile.ZipFile("test.zip", "r") as z:
    z.extractall(path="zzz2")
    # 展開せずファイルを見る
    with z.open("test_dir/test.txt") as f:
        print(f.read())

tempfile

import tempfile

# tmpファイルに書き込み
with tempfile.TemporaryFile(mode="w+") as t:
    t.write("hello")
    t.seek(0)
    print(t.read())

# tmpファイルを削除したくないとき delete=Falseにする
with tempfile.NamedTemporaryFile(delete=False) as t:
    # パスの表示
    print(t.name)
    with open(t.name, "w+") as f:
        f.write("test\n")
        f.seek(0)
        print(f.read())

# tmpディレクトリ
with tempfile.TemporaryDirectory() as td:
    print(td)

subprocess でコマンドを実行する

import subprocess

# os.system("ls") は、最近は仕様しない subprocess を利用すること。subprocessの方が高機能
subprocess.run(["ls"])  # lsコマンドと同じ
subprocess.run(["ls", "-al"])  # lsコマンドと同じ
subprocess.run(["ls -al"], shell=True)  # シェルぽく書く パイプとかを利用するとき使う

# r = subprocess.run(["lsa"], shell=True)  # 存在しないコマンド
# print(r)  # => /bin/sh: lsa: command not found エラーの確認

# subprocess.run(["lsa"], shell=True, check=True)  # エラーをスローするときはcheck=Trueを付ける。

# shell=False でパイプを利用する方法
p1 = subprocess.Popen(["ls", "-al"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "test"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
output = p2.communicate()[0]
print(output)

datetime

import datetime

now = datetime.datetime.now()
print(now)  # => 2024-04-22 19:01:29.954194
print(now.isoformat())  # => 2024-04-22T19:01:29.954194
print(now.strftime("%d/%m/%y-%H%M%S%f"))  # => 22/04/24-190129954194

today = datetime.date.today()
print(today)  # => 2024-04-22
print(today.isoformat())  # => 2024-04-22
print(today.strftime("%d/%m/%y"))  # => 22/04/24

t = datetime.time(hour=1, minute=10, second=5, microsecond=100)
print(t)  # => 01:10:05.000100
print(t.isoformat())  # => 01:10:05.000100
print(t.strftime("%H_%M_%S_%f"))  # => 2024-04-15 19:01:29.954194

# 下記2つは同じ出力です。引いて足すか、足して引くか。
d = datetime.timedelta(weeks=-1)
print(now + d)  # => 2024-04-15 19:01:29.954194
d = datetime.timedelta(weeks=+1)
print(now - d)  # => 2024-04-15 19:01:29.954194