Akademik Bilişim 2017 Gnu/Linux sistemler için Python - 2. Gün


        Akademik Bilişim öncesi kurslarda ikinci gün de geride kaldı. Bugüne Python'da dosya işlemleri ile başladık daha sonra Unix sinyallerini ve soketlerini işledik. Soketler konusunu bir ağ yöneticisi kadar derinlemesine incelemedik ama uygulamalar arası iletişim için soketlerin nasıl kullanılacağını öğrendik, yarın da pekiştirmeye devam edeceğiz. 

        Günün sonuna yaklaşırken argüman yönetimi için birkaç modül(subprocess, psutil) kullandık. Linux'da dosya sitemlerindenve kullanıcı izinlerinden bahsettik ve yine gün boyunca öğrendiğimiz konuları tecrübe etmemizi sağlayacak bir uygulama ile bugünü tamamladık. Bundan sonraki bölüm derste tuttuğum ve çeşitli sayfalardan tamamladığım notlar ile kodlardan oluşmakta.


Dosya İşlemleri:

        Program kapatıldıktan sonra kullanıcıdan alınan verilere ulaşılamaz. Eğer bu verileri kaybetmek istemiyorsak bunları dosyalara yazmak gerekir. Aynı anda okuma ve yazma veya aynı anda iki yazma işlemi yapılamaz. Aynı anda bir dosyayı sadece bir kullanıcı açabilir.

Dosyaları Açmak:

        Python dilinde dosya işlemlerini gerçekleştirebilmek için öncelikle dosyaların açılması gerekir. Dosya açmak için open() fonksiyonu kullanılır. Temel olarak;

f = open(dosya_adı, kip)

Kipler:

        open fonksiyonuna ikinci parametre olarak dosyanın nasıl kullanılacağı yani ne şekilde açılacağı bilgisi verilir. Eğer parametre verilmemişse 'r' oolduğu varsayılır. En çok kullanılan kipler:

  •  w: Sadece yazma kipidir. Aynı isimde bir dosya varsa üzerine yazılır.
    • w+: Dosyayı hem okumak hem de yazmak için açan kiptir.
  • r: Sadece okuma kipidir.
    • r+: Dosyayı hem okumak hem de yazmak için açan kiptir.
  • a: Dosya sonuna yazma kipidir.
    • a+: Dosyayı hem okumak hem de sonuna yazmak için açan kiptir.
Dosyalara Yazmak:

        Yazmak üzere açılmış bir dosya nesnesine yazmak için write() fonksiyonu kullanılır. Dosyada yapılan değişikliklerin disk üzerine kaydedilebilmesi için flush() fonksiyonu kullanılmalıdır.

dosya = open('/home/user/test.txt','a+')
dosya.write('Eklenecek metin')

Dosyarı Okumak:
  • f.read(): Bütün dosyayı bir seferde okur ve tek bir dize olarak geri verir.
  • f.readline(): Dosyadan tek bir satır okur. Satırların sonundaki "\n" karakteri korunur.
  • f.readlines():Dosya içindeki bütün satırların bulunduğu bir liste geri döndürür.
Dosyaları Kapatmak:

        Python belirli bir sayıdan sonra dosya açmaya izin vermez. Bu yüzden açılan dosyaları kapatmak önemlidir. Dosyaları kapatmak için close() fonksiyonu kullanılır.  Bu fonksiyon programın dosyayla işinin bittiğini ifade eder.

dosya.close()

dosya_islemleri.py:
import sys

dosya = open("cikti.txt", "a+")
a = sys.stdout
sys.stdout = dosya
print("hello world")        # standart çıktı bir dosyaya yönlendirildi
sys.stdout = a              # standart çıktı tekrar ekrana yazdırıldı

#file = open("deneme.txt", "w+")    # dosya yazılmak için açıldı, w+ verileri siler baştan yazar
file = open("deneme.txt", "a+")     # dosya yazılmak için açılır fakat veriler silinmez dosyanın sonuna eklenir

file.write("Sedat Ak\n")
file.flush()
print("Akademik Bilisim 17", file = file)
print("imlecin yeri {}".format(file.tell()))
file.seek(5)
print("imleç konumlandırıldı {}".format(file.tell()))   # İmlecin yeri hesaplandı

file.close()    # deneme.txt dosyası kapatıldı

with open("run.py", "r") as dosyam:       # with sayesinde girdiden çıkıldığında dosya kapanır
    print("-----")
    satirlar = [satir[:-1] for satir in dosyam.readlines()]
    # okunan satırları liste formatına çevirir ve üzerinde işlem yapmamızı sağlar
    #satirlar = [satir[:-1] for satir in dosyam.readlines() if satir.startswith("import")]
    # import ile başlayan satırları okuduk
    #satirlar = [satir[:-1] for satir in dosyam.readlines() if not satir.startswith(" ") and satir[:-1]]
    # başında boşluk olmayanları getirecek ve satır boş olmayacak
    print(satirlar)
    #print(dosyam.readlines())       # tüm satırları liste haline getirdi
    print("-----")
    print("Dosyam kapandı mı? {}".format(dosyam.close()))   # dosya kapalı değil
print("Dosyam kapandı mı? {}".format(dosyam.closed))        # dosya kapandı

Sinyaller:

        Kullanıcı pragram üzerinde fare ya da kalvyedeki herhangi bir tuşa tıkladığında sinyaller oluşur. Sinyaller sayesinde program üzerinde meydana gelen olayları kontrol edebilir ve uygulama ile iletişim kurulabilir. Bir uygulamayı kapatmak için; kapan sinyali yollandığında gelecek sinyale göre bir fonksiyon çağrılır. 9 ya da 15 numaralı sinyal alınınca program kapanır. 100 den büyük numaralı sayılar hata kodlarıdır. Sinyale 100 eklersek o sinyalin hata kodlarını elde etmiş oluruz.

run.py:
import os
import sys
import signal
import gozcu

def term_handle(sig, stack):
    print("{} numaralı sinyal alındı".format(sig), file=sys.stderr, flush=True)
    exit(100 + sig)     # hata kodu gösterimi

def int_handle(sig, stack):
    print("Kapanacak?", file=sys.stderr, flush=True)

def usr1_handle(sig, stack):
    print("PID: {}".format(os.getpid()), file=sys.stderr, flush=True)

def usr2_handle(sig, stack):
    sys.stdout = open(os.devnull, "w")

signal.signal(signal.SIGTERM, term_handle)
signal.signal(signal.SIGINT, int_handle)
signal.signal(signal.SIGUSR1, usr1_handle)
signal.signal(signal.SIGUSR2, usr2_handle)

try:
    print("PID: {}".format(os.getpid()))        # uygulamanın id'si
    #gozcu.ana_fonksiyon()
except Exception as e:      # Hata yakalandı ve e değişkenine atandı
    print("An error occured:", file=sys.stderr)     # stderr'e yazdırıldı
    print("{cls}({args})".format(cls=type(e).__name__, args=", ". join(e.args)), file=sys.stderr)
    # hatanın ismi ve mesajı alındı ve stderr'e yazdırıldı
    exit(1)
else:
    exit(0)     #normal çıkış kodu
Programın çıktısı:
PID: 14607

Terminalde:
$ sudo kill 15 14607

Programın çıktısı güncellendi:
15 numaralı sinyal alındı

Soketler:

        İki sistem arasındaki haberleşmeyi, veri alışverişini ve kontrolleri sağlar. Örneğin; istemci ile sunucu arasındaki bağlantıyı sağlar. Soket programlama yapmak için gereken kütüphane 'socket'tir. Bizim yaptığımız örnekte IP soketinden UDP kullanıldı.

istemci.py:
from socket import *

sunucuAd, sunucuPort = 'localhost', 12345
istemciSoket = socket(AF_INET, SOCK_DGRAM)      # datagram

while True:
    op = input('İşlem (B)üyült, (K)üçült, (Ç)ık: ').lower()     # op: operatör
    if op not in "bkç":
        print("Hatalı Giriş")
        continue        # soruyu tekrar sordurur
    if op == "ç":
        mesaj = ""
    else:
        mesaj = input('Küçük harfle bir cümle yazınız: ')
    mesaj = (op + "-" + mesaj).encode()     # UTF'den ASCII formatına çevirdik
    istemciSoket.sendto(mesaj, (sunucuAd, sunucuPort))      # mesajı gitmesi gereken sunucu ve porta gönder
    yeniMesaj, sunucuAdres = istemciSoket.recvfrom(4096)        # 4KB'lık mesajlar alındı
    yeniMesaj = yeniMesaj.decode()          # sunucudan gelen mesajı ASCII'den UTF'e geri çevirdik
    print("Alınan cevap: {}".format(yeniMesaj))
    if yeniMesaj == "ç":
        break

print("Kapatma mesejının cevabı alındı. İstemci kapanıyor.")
istemciSoket.close()
print("İstemci Kapandı!")

sunucu.py:
from socket import *

sunucuAd, sunucuPort = 'localhost', 12345
sunucuSocket = socket(AF_INET, SOCK_DGRAM)       # datagram / IP protokolünden çalışsın
sunucuSocket.bind((sunucuAd, sunucuPort))        # soketi verilen port üzerinden host'a bağlar
print('Sunucu veri almaya hazırdır')

isimler = {"b": "Büyült", "k": "Küçült", "ç": "Çıkış"}
islemler = {"b": str.upper, "k": str.lower, "ç": lambda x: "ç"}

while True:
    mesaj, istemciAdres = sunucuSocket.recvfrom(4096)       # recvfrom: mesaj alır
    op, mesaj = mesaj.decode().split("-")
    print("İstemciden {} işlemi için mesaj alındı: ".format(isimler[op]), mesaj)
    yeniMesaj = islemler[op](mesaj)
    print("Mesaj istemciye geri gönderilecek: ", yeniMesaj)
    yeniMesaj = yeniMesaj.encode()
    sunucuSocket.sendto(yeniMesaj, istemciAdres)
    if op == "ç":
        break

print("Kapatma mesajı alındı. Sunucu kapanıyor.")
sunucuSocket.close()        # soketi kapatır
print("Sunucu Kapandı.")

subprocess Modülü:

        Bir uygulama içerisinde başka bir uygulamayı çalıştırmaya yarar. Herhangi bir uygulamayı python içerisinden kullanmak için subprocess modülü kullanılır. Etkileşimli kabukta;

>>> import subprocess
>>> subprocess.call(["charm"])# Pycharm'ı python içerisinden çalıştırır
>>> x = subprocess.call("ls") # ls komutunu python içersinden çalıştırır
>>> x = subprocess.check_output("ls")

psutil Modülü:

Kurulumu:
$ sudo apt-get install python3-psutil

Çalıştırma:
$ python3
>>> import psutil
>>> dir(psutil)
['AccessDenied', 'BOOT_TIME', 'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED', 'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN', 'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT', 'Error', 'IOPRIO_CLASS_BE', 'IOPRIO_CLASS_IDLE', 'IOPRIO_CLASS_NONE', 'IOPRIO_CLASS_RT', 'NUM_CPUS', 'NoSuchProcess', 'Popen', 'Process', 'RLIMIT_AS', 'RLIMIT_CORE', 'RLIMIT_CPU', 'RLIMIT_DATA', 'RLIMIT_FSIZE', 'RLIMIT_LOCKS', 'RLIMIT_MEMLOCK', 'RLIMIT_MSGQUEUE', 'RLIMIT_NICE', 'RLIMIT_NOFILE', 'RLIMIT_NPROC', 'RLIMIT_RSS', 'RLIMIT_RTPRIO', 'RLIMIT_RTTIME', 'RLIMIT_SIGPENDING', 'RLIMIT_STACK', 'RLIM_INFINITY', 'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED', 'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKING', 'STATUS_ZOMBIE', 'TOTAL_PHYMEM', 'TimeoutExpired', '_POSIX', '_PY3', '_TOTAL_PHYMEM', '_WINDOWS', '__all__', '__author__', '__builtins__', '__cached__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__file__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__loader__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__package__', '__path__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__spec__', '__str__', '__subclasshook__', '__version__', '__weakref__', '_assert_pid_not_reused', '_common', '_compat', '_deprecated', '_deprecated_method', '_last_cpu_times', '_last_cpu_times_2', '_last_per_cpu_times', '_last_per_cpu_times_2', '_module', '_nt_sys_diskio', '_nt_sys_netio', '_pmap', '_pslinux', '_psplatform', '_psposix', '_timer', '_wraps', 'avail_phymem', 'avail_virtmem', 'boot_time', 'cached_phymem', 'callable', 'cpu_count', 'cpu_percent', 'cpu_times', 'cpu_times_percent', 'defaultdict', 'disk_io_counters', 'disk_partitions', 'disk_usage', 'errno', 'get_pid_list', 'get_process_list', 'get_users', 'net_connections', 'net_io_counters', 'network_io_counters', 'os', 'phymem_buffers', 'phymem_usage', 'pid_exists', 'pids', 'process_iter', 'pwd', 'signal', 'subprocess', 'swap_memory', 'sys', 'test', 'time', 'total_virtmem', 'used_phymem', 'used_virtmem', 'users', 'version_info', 'virtmem_usage', 'virtual_memory', 'wait_procs', 'warnings']
>>> psutil.avail_phymem()/1024**2
777.0703125
>>> psutil.cpu_count()
4
>>>len(psutil.net_connections())
73
>>> psutil.cpu_times()
scputimes(user=2829.26, nice=20.32, system=882.54, idle=41184.0, iowait=727.83, irq=0.01, softirq=1.58, steal=0.0, guest=0.0, guest_nice=0.0)

CPU kullanımını önizleme Örneği 1:
>>>suan = psutil.cpu_times()
>>>while True:
>>> gelecek = psutil.cpu_times()
>>> if gelecek.user > suan.user:
>>>  suan = gelecek
>>>  print("CPU Kullanımda")
>>> import time
>>> time.sleep(1)

CPU Kullanımı Önizleme Örneği 2:
while True:
 if max(psutil.cpu_percent(percpu=True))>80
  print("CPU Kullanımı Yüksek")
 if psutil.virtual_memory().percent>60
  print("RAM Kullanımı Yüksek")
 time.sleep(0.5)