Paepoi

スポンサードリンク
Paepoi » PyGObject Tips » Gio(PyGObject) Tips

Gio(PyGObject) Tips

# 最終更新日 2019.07.20

Python2 関連の削除、点在していた GFile 関連を整理
文字列をシングルクォートに統一、及び fstring 化(python 3.6 以降)を行いました

GFile 基本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python3
 
'''
    ファイルの作成、書き込み、コピー、ゴミ箱へ移動
    は GIR ではすべて GFile のメソッドで行います
'''
 
from gi.repository import Gio
 
# 以下を都合のいいように変更してください
FILENAME = '新規ファイル.txt'
CONTENTS = '内容\nです'.encode('utf8')
COPYFILE = 'コピー.txt'
 
# GFile の作成は存在しないファイルでもいい
f = Gio.file_new_for_path(FILENAME)
 
# 存在しないことの確認
print(f.query_exists())
#=> False
 
# 新規作成、この関数を呼んだ時点でファイルは作られる
ostream = f.create(Gio.FileCreateFlags.NONE)
 
# 上書きの場合は replace を使う、実は新規でも使える
# 第二引数を True にすると 新規ファイル.txt~ が自動で作られる
#ostream = f.replace(None, False, Gio.FileCreateFlags.NONE)
 
# 戻り値の GFileOutputStream を使ってファイル内容を書き込む
# 文字列の場合は UTF-8 に変換するのを忘れずに
ostream.write(CONTENTS)
 
# 閉じる、この後何もしないならガベージコレクションにまかせてもいい
ostream.close()
 
# コピー、詳細不要なら以下でいい
c = Gio.file_new_for_path(COPYFILE)
f.copy(c, Gio.FileCopyFlags.NONE)
 
# ゴミ箱へ移動
f.trash()
 
# COPYFILE が存在して FILENAME がゴミ箱に入っていることを確認

ファイルの詳細を得る
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python3
 
'''
    g_file_query_info の引数に得たい情報をコンマ区切りで指定し GFileInfo を得る
    FileInfo オブジェクトのメソッドで情報を出力、という流れで取得できます
    ファイルの種類(Description) は Content Type から変換します
    存在するファイルであれば拡張子は関係無く詳細を取得できる
'''
 
import sys
from gi.repository import Gio
 
attr = ','.join([
    Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
    Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
    Gio.FILE_ATTRIBUTE_STANDARD_SIZE ])
 
# このスクリプト自身の詳細を得る
f = Gio.file_new_for_path(__file__)
 
# g_file_query_info
info = f.query_info(attr, Gio.FileQueryInfoFlags.NONE)
 
# Content Type を先に得ておく
ct = info.get_content_type()
 
# 出力
print(f'''----------
Name        : {info.get_display_name()}
Size        : {info.get_size()} byte
Content Type: {ct}
Mime Type   : {Gio.content_type_get_mime_type(ct)}
Description : {Gio.content_type_get_description(ct)}
----------''')

ファイルの詳細を得る(簡易版)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/env python3
 
'''
    ファイルの中身をみないどころか存在すら関係ない版
    Gio.content_type_guess は拡張子依存のようです
    result_uncertain は確実性ですが中身を見ないのでほぼ意味無い
'''
 
from gi.repository import Gio
 
# 拡張子から ContentType を得る
ctype = Gio.content_type_guess('a.xml')
print(ctype)
#=> ('application/xml', result_uncertain=False)
 
# 不明拡張子ならバイナリ扱い、存在しても中身は見ない
b = Gio.content_type_guess('a.homura')
print(b)
#=> ('application/octet-stream', result_uncertain=True)
 
# 説明を得る
desc = Gio.content_type_get_description ('application/xml')
print(desc)
#=> XML ドキュメント
 
# サブセットであるか(以下はテキストファイルであるか)
sub = Gio.content_type_is_a('application/xml', 'text/plain')
print(sub)
#=> True
 
# 実行可能か(+x 属性が付いているかどうかではない)
x = Gio.content_type_can_be_executable('application/x-shellscript')
print(x)
#=> True
 
# ここから GAppInfo
appinfo = Gio.app_info_get_default_for_type('text/plain', False)
 
# デフォルトアプリ
defapp = appinfo.get_name() # or executable()
print(defapp)
#=> テキストエディター

非同期読み込み
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python3
  
'''
    同期読み込みでいいなら下記ストリーミング I/O を
    又は f.load_contents にて一気読みしてください
'''
 
from gi.repository import GLib, Gio
 
def on_read_file(gfile, res):
    r, contents, etag = gfile.load_contents_finish(res)
    print(contents.decode())
    mainloop.quit()
 
f = Gio.file_new_for_path(__file__)
 
# 非同期読み込み開始
f.load_contents_async(None, on_read_file)
 
# メインループが必要
# GUI で使う場合は Gtk.main() が担当するので必要無い
mainloop = GLib.MainLoop()
mainloop.run()

ストリーミング I/O
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env python3
 
'''
    こちらを使う場合 Python 文字列と UTF-8 は自動変換されます
'''
 
from gi.repository import Gio
 
FILENAME = 'suzuki.txt'
TEXT = 'スズキはスクーターも\n\nカッコイイ〜!'
 
# Write
f = Gio.file_new_for_path(FILENAME)
fstream = f.create(Gio.FileCreateFlags.NONE)
dstream = Gio.DataOutputStream(base_stream=fstream)
dstream.put_string(TEXT)
fstream.close()
 
# Read
f = Gio.file_new_for_path(FILENAME)
fstream = f.read()
dstream = Gio.DataInputStream(base_stream=fstream)
while True:
    # line に lf は入らない、length はバイト単位
    # line == '' では空文字を判定する、EOF で None になる
    line, length = dstream.read_line_utf8()
    if line == None:
        break
    print(line)
fstream.close()

ディレクトリ内容列挙
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python3
 
from gi.repository import Gio, GLib
 
# ディレクトリも GFile
d = Gio.file_new_for_path(GLib.get_home_dir())
 
# 表示名と隠しファイルかどうかを得る
enum = d.enumerate_children(
    'standard::display-name,standard::is-hidden',
    Gio.FileQueryInfoFlags.NONE)
 
# info は GFileInfo
for info in enum:
    if not info.get_is_hidden():
        print(info.get_display_name())

ディレクトリを監視
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env python3
 
'''
    ホームディレクトリを監視するサンプル
    GFileMonitor の changed シグナルが変更毎に飛んできます
'''
 
# mainloop を強制終了させるため
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
 
from gi.repository import Gio, GLib
 
def on_monitor(monitor, f, other_f, event):
    '''
        隠しファイルの変更も感知します( /.bash.history 等 )
        作成は上書きやリネームでも反応します
    '''
    s = f.get_basename()
    # 隠しファイルは無視、ココを消すと何故かが解る
    if s.startswith('.'): return
    if event == Gio.FileMonitorEvent.CHANGED:
        print(f'{s} の内容が変更されました')
    elif event == Gio.FileMonitorEvent.CHANGES_DONE_HINT:
        print(f'{s} のファイル情報が変更されました')
    elif event == Gio.FileMonitorEvent.DELETED:
        print(f'{s} が削除又は移動されました')
    elif event == Gio.FileMonitorEvent.CREATED:
        print(f'{s} が作成されました')
    elif event == Gio.FileMonitorEvent.ATTRIBUTE_CHANGED:
        print(f'{s} のパーミッションが変更されました')
 
f = Gio.File.new_for_path(GLib.get_home_dir())
monitor = f.monitor(Gio.FileMonitorFlags.NONE)
monitor.connect('changed', on_monitor)
print('終了するには Ctrl+C を行ってください')
# メインループ
mainloop = GLib.MainLoop()
mainloop.run()

Copyright(C) sasakima-nao All rights reserved 2002 --- 2025.