sys Modülü

Tıpkı os modülü gibi, sys de Python programlama dilindeki önemli standart kütüphane modüllerinden biridir. Bu modül, kullandığınız Python sürümü ile ilgili bilgi edinmenizi ve kullandığınız Python sürümü ile çeşitli işlemler yapabilmenizi sağlar.

Bütün modüllerde olduğu gibi, bu modülü de şu komutla içe aktarıyoruz:

>>> import sys

Bu modülün içinde hangi nitelik ve fonksiyonların olduğunu görmek için şu komutu kullanabileceğinizi biliyorsunuz:

>>> dir(sys)

Gördüğünüz gibi bu modül içinde de epeyce fonksiyon ve nitelik var. Biz bu bölümde, sys modülünün en yaygın kullanılan, en önemli fonksiyon ve niteliklerini ele alacağız.

İlk olarak exit() fonksiyonu ile başlayalım…

sys.exit()

sys modülünün exit() fonksiyonunu kullanarak, programınızın işleyişini durdurabilir, programınızı kapanmaya zorlayabilirsiniz. Basit bir örnek verelim:

import sys

sayı = input('Bir sayı girin: ')

if int(sayı) < 0:
    print('çıkılıyor...')
    sys.exit()

else:
    print(sayı)

Eğer kullanıcı 0’dan küçük bir sayı girerse programımız sys.exit() komutunun etkisiyle çalışmayı durdurup kapanacaktır.

sys.argv

sys modülünün argv niteliği, yazdığımız program çalıştırılırken kullanılan parametreleri bir liste halinde tutar.

Gelin isterseniz bunun ne demek olduğunu bir örnek üzerinde gösterelim.

Şimdi mesela masaüstünde deneme.py adlı bir dosya oluşturun ve içine şunları yazın:

import sys
print(sys.argv)

Bu programı şu komutla çalıştırın:

python deneme.py

Programı çalıştırdığınızda şuna benzer bir çıktı alacaksınız:

['deneme.py']

Gördüğünüz gibi, sys.argv komutu bize bir liste veriyor. Bu listenin ilk öğesi, yazdığımız programın adı. Yani deneme.py.

Şimdi aynı programı bir de şu şekilde çalıştıralım:

python deneme.py parametre

Bu defa programımız bize şu çıktıyı verecek:

['deneme.py', 'parametre']

Gördüğünüz gibi, sys.argv komutu, programın ismi ile birlikte, bu programa parametre olarak verilen değerleri de bir liste halinde saklıyor. Bu oldukça önemli ve kullanışlı bir özelliktir. Bu özellikten pek çok farklı şekillerde yararlanabilirsiniz.

Mesela:

import sys

def çık():
    print('Çıkılıyor...')
    sys.exit()

if len(sys.argv) < 2:
    print('Gerekli parametreleri girmediniz!')
    çık()

elif len(sys.argv) > 2:
    print('Çok fazla parametre girdiniz!')
    çık()

elif sys.argv[1] in ['-v', '-V']:
    print('Program sürümü: 0.8')

else:
    mesaj = 'Girdiğiniz parametre ({}) anlaşılamadı!'
    print(mesaj.format(sys.argv[1]))
    çık()

Burada öncelikle modülümüzü içe aktardık:

import sys

Bunu yapmadan, o modülü kullanamayacağımızı biliyorsunuz.

Ardından çık() adlı bir fonksiyon tanımladık:

def çık():
    print('Çıkılıyor...')
    sys.exit()

Programı sonlandırmak istediğimizde bu fonksiyonu kullanacağız.

Daha sonra şöyle bir if bloğu oluşturduk:

if len(sys.argv) < 2:
    print('Gerekli parametreleri girmediniz!')
    çık()

Eğer sys.argv listesinin uzunluğu 2’den düşükse, programımız herhangi bir parametre olmadan, yalnızca ismiyle çalıştırılmış demektir. Bu durumda kullanıcıya ‘Gerekli parametreleri girmediniz!’ mesajını gösterip programı sonlandırıyoruz.

Sonraki kod bloğumuz şöyle:

elif len(sys.argv) > 2:
    print('Çok fazla parametre girdiniz!')
    çık()

Eğer sys.argv listesi 2’den büyükse, programımız birden fazla parametre ile çalıştırılmış demektir. Bu durumda kullanıcıya ‘Çok fazla parametre girdiniz!’ mesajını gösterip yine programı sonlandırıyoruz.

Bir sonraki kodlarımız şöyle:

elif sys.argv[1] in ['-v', '-V']:
    print('Program sürümü: 0.8')

Eğer sys.argv listesinin ikinci öğesi -v veya -V ise programımızın sürüm bilgisini veriyoruz.

Son olarak da şu bloğu yazıyoruz:

else:
    mesaj = 'Girdiğiniz parametre ({}) anlaşılamadı!'
    print(mesaj.format(sys.argv[1]))
    çık()

Kullanıcının -v veya -V dışında bir parametre girmesi durumunda ise, girilen parametrenin anlaşılamadığı konusunda kullanıcıyı bilgilendirip programdan çıkıyoruz.

Aşağıda, programımızın hangi komutlara hangi karşılıkları verdiğini görüyorsunuz:

C:\Users\fozgul\Belgelerim> python deneme.py
Gerekli parametreleri girmediniz!
Çıkılıyor...

C:\Users\fozgul\Belgelerim> python deneme.py -a
Girdiğiniz parametre (-a) anlaşılamadı!
Çıkılıyor...

C:\Users\fozgul\Belgelerim> python deneme.py -a -b
Çok fazla parametre girdiniz!
Çıkılıyor...

C:\Users\fozgul\Belgelerim> python deneme.py -v
Program sürümü: 0.8

C:\Users\fozgul\Belgelerim> python deneme.py -V
Program sürümü: 0.8

sys.executable

Eğer, yazdığınız bir programda, programınızın çalıştığı sistemdeki Python’ın çalıştırılabilir dosyasının adını ve yolunu öğrenmeniz gerekirse bu niteliği kullanabilirsiniz:

>>> sys.executable

C:\Python37python.exe

sys.getwindowsversion()

Bu fonksiyon, kullanılan Windows sürümüne ilişkin bilgi verir:

>>> sys.getwindowsversion()

sys.getwindowsversion(major=5, minor=1, build=2600,
platform=2, service_pack='Service Pack 3')

Uyarı

Bu fonksiyon yalnızca Windows’ta çalışır. GNU/Linux’ta bu fonksiyon tanımlı değildir.

Bu fonksiyon kendi içinde de bazı nitelikler barındırır. Bunları görmek için şu komutu kullanabilirsiniz:

>>> ver = sys.getwindowsversion()
>>> dir(ver)

['__add__', '__class__', '__contains__', '__delattr__',
 '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
 '__getattribute__', '__getitem__', '__getnewargs__',
 '__gt__', '__hash__', '__init__', '__iter__', '__le__',
 '__len__', '__lt__', '__mul__', '__ne__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__rmul__',
 '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
 'build', 'count', 'index', 'major', 'minor', 'n_fields',
 'n_sequence_fields', 'n_unnamed_fields', 'platform',
 'product_type', 'service_pack', 'service_pack_major',
 'service_pack_minor', 'suite_mask']

Bu niteliklere erişmek için şu söz dizimini kullanabilirsiniz:

>>> ver.service_pack()

sys.path

Modüller konusunu işlerken sys modülünün path niteliğinden söz etmiştik. O yüzden orada söylediklerimizi tekrarlamayacağız.

sys.platform

os modülünü incelerken öğrendiğimiz name niteliği gibi, sys modülünün platform adlı niteliği de, kodlarımızın çalıştığı işletim sistemi hakkında bize bilgi verir:

>>> sys.platform

Eğer bu komutu GNU/Linux’ta verirsek linux çıktısı, Windows’ta verirsek win32 çıktısı, Mac OS X’te verirsek darvin çıktısı alırız.

sys.prefix

sys modülünün prefix niteliği Python’ın hangi dizine kurulduğunu gösterir:

>>> sys.prefix

'/home/local/python'

Veya:

>>> sys.prefix

'C:\\Python'

sys.ps1

sys modülünün ps1 niteliği, etkileşimli kabuktaki ‘>>>’ işaretini tutar:

>>> sys.ps1

'>>> '

Eğer isterseniz bu işareti değiştirebilirsiniz:

>>> sys.ps1 = '+++ '

Bu komutu verdikten sonra ‘>>>’ işaretinin ‘+++’ olarak değiştiğini göreceksiniz.

sys.ps2

Etkileşimli kabukta Python bizden girdiğimiz kodların devamını beklediğini göstermek için ‘…’ işaretini kullanır:

>>> a = 5
>>> if a == 5:
...

sys modülünün ps2 niteliği, işte etkileşimli kabuktaki devam satırlarında gördüğümüz bu ‘…’ işaretini tutar:

>>> sys.ps2

'... '

Eğer isterseniz bu işareti değiştirebilirsiniz:

>>> sys.ps1 = '--- '

Bu komutu verdikten sonra ‘…’ işaretinin ‘—’ olarak değiştiğini göreceksiniz.

sys.version

sys modülünün version niteliği kullandığınız Python sürümüne ilişkin ayrıntılı bilgi verir:

>>> sys.version

'3.7.0 (default, 19.08.2024, 12:24:55)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux'

sys.version_info

sys modülünün version_info niteliği de kullandığınız Python sürümüne ilişkin bilgi verir:

>>> sys.version_info

sys.version_info(major=|major3|, minor=|minor3|, micro=|micro3|, releaselevel='final', serial=0)

Bu nitelik kendi içinde birtakım başka nitelikler de barındırır:

>>> dir(sys.version_info)

['count', 'index', 'major', 'micro', 'minor',
 'n_fields', 'n_sequence_fields', 'n_unnamed_fields',
 'releaselevel', 'serial']

Bu niteliklere nasıl ulaşacağınızı biliyorsunuz:

>>> sys.version_info.major #büyük sürüm numarası
>>> sys.version_info.minor #küçük sürüm numarası
>>> sys.version_info.micro #minik sürüm numarası

sys.winver

sys modülünün winver niteliği Python’ın büyük sürüm numarasıyla küçük sürüm numarasını verir:

>>> sys.winver

3.7

Uyarı

Bu nitelik yalnızca Windows’ta çalışır; GNU/Linux’ta tanımlı değildir.

sys.stdout

Önceki derslerimizden de bildiğiniz gibi stdout, ‘standart çıktı konumu’, yani programlarımızın çıktılarını standart olarak verdikleri konum anlamına geliyor.

Python’da yazdığımız programlar çıktılarını standart olarak komut satırına verir. Yani mesela:

>>> print('merhaba zalim dünya')

komutunu verdiğimizde, bu komutun çıktısı komut ekranında görünecektir.

Python’da standart çıktı konumununun neresi olacağı bilgisi sys modülünün stdout adlı niteliği içinde tutulur:

>>> import sys
>>> sys.stdout

<_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1254'>

Standart çıktı konumuna yazmanın en yaygın yolunun print() komutunu kullanmak olduğunu biliyoruz. Bu komut, standart çıktı konumu neresi ise oraya yazacaktır.

Standart çıktı konumuma yazmanın başka bir yolu da doğrudan sys.stdout niteliğinin write() metodunu kullanmaktır.

Dikkatlice bakın:

>>> sys.stdout.write('merhaba zalim dünya')

print() komutundan farklı olarak sys.stdout.write() fonksiyonu şöyle bir çıktı verir:

merhaba zalim dünya19

Burada, çıktının sonundaki 19 sayısı ‘merhaba zalim dünya’ karakter dizisinin uzunluğunu gösteriyor. sys.stdout.write() fonksiyonu etkileşimli kabukta kullanıldığında böyle bir çıktı verir. Ama eğer bu kodları bir dosyaya yazıp çalıştırırsanız sonraki 19 sayısı görünmez.

Bu arada, her ne kadar print() ve sys.stdout.write() birbirine benzese de aralarında önemli farklar bulunur. Örneğin print() fonksiyonu parametre olarak her türlü veri tipini alabilir. Ancak sys.stdout.write() fonksiyonu parametre olarak yalnızca karakter dizisi alabilir:

>>> sys.stdout.write(12)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str, not int

Dolayısıyla sys.stdout.write() fonksiyonuna parametre olarak vereceğiniz değeri öncelikle karakter dizisine çevirmeniz gerekir:

>>> sys.stdout.write(str(12))

122

Not

Sondaki 2 sayısının ‘12’ karakter dizisinin uzunluğunu gösterdiğini söylemiştik. Bu kodları dosyaya yazıp çalıştırdığınızda yalnızca 12 çıktısı alırsınız.

print() ile sys.stdout.write() arasındaki önemli bir fark da, print() fonksiyonu yazma işleminden sonra bir sonraki satıra geçerken, sys.stdout.write() fonksiyonunun geçmemesidir.

Uyarı

sys.stdout.write() fonksiyonu etkileşimli kabuktan çalıştırıldığında ve dosyadan çalıştırıldığında birbirinden farklı çıktılar verir. O yüzden aşağıdaki örnekleri dosyaya yazıp çalıştırmanızı tavsiye ederim.

Mesela şu örneğe bakalım:

for i in 'istihza':
    print(i)

Bu komut şu çıktıyı verir:

i
s
t
i
h
z
a

Gördüğünüz gibi, print() fonksiyonu, döngüye giren her öğeyi yeni satıra basıyor.

Bir de sys.stdout.write() fonksiyonunun ne yaptığına bakalım:

import sys

for i in 'istihza':
    sys.stdout.write(i)

Bu komutlar ise şu çıktıyı verir:

istihza

Gördüğünüz gibi, sys.stdout.write() fonksiyonu öğelerin hepsini aynı satıra bastı. Eğer öğelerin ayrı satırlara basılmasını istiyorsanız bunu açıkça belirtmelisiniz:

import sys

for i in 'istihza':
    sys.stdout.write(i+'\n')

sys.stdout.write() fonksiyonunun otomatik olarak satır başı karakterini basmıyor oluşunu kullanarak kronometre benzeri bir program yazabilirsiniz:

import sys

sayaç = 0

while True:
    sys.stdout.write(str(sayaç)+'\r')
    sayaç += 1

Burada, önceki derslerimizde öğrendiğimiz kaçış dizilerinden \r’yi kullanarak, her öğenin ekrana basılmasının ardından satırın en başına dönülmesini sağladık. Böylece öğeler yan yana değil de birbirlerinin üstüne basılmış oldu.

Bu arada, eğer yukarıdaki kodlar herhangi bir çıktı vermeden bekliyorsa, kodları şu şekilde yazın:

import sys

sayaç = 0

while True:
    sys.stdout.write(str(sayaç)+'\r')
    sys.stdout.flush()
    sayaç += 1

Burada eklediğimiz sys.stdout.flush() satırı, Python’ın tamponda beklettiği verileri çıktıya göndermesini sağlar. Siz bu ‘flush’ kavramını print() fonksiyonundan hatırlıyor olmalısınız (print() fonksiyonunun flush parametresi).

Hatırlarsanız, ‘flush’ kavramının yanısıra, print() fonksiyonunu işlerken öğrendiğimiz bir başka kavram da standart çıktı konumunun değiştirilmesi idi. print() fonksiyonuna verdiğimiz file parametresi yardımıyla programlarımızın standart olarak çıktı verdiği konumu değiştirebiliyorduk:

f = open('çıktılar.txt', 'w')
print('merhaba zalim dünya', file=f)

Burada çıktılar.txt adlı bir dosya oluşturduk ve bunu print() fonksiyonunun file parametresine atayarak, çıktıları komut satırı yerine çıktılar.txt adlı dosyaya gönderdik.

Aynı işlemi sys.stdout aracılığıyla da yapabileceğimizi biliyorsunuz:

import sys

f = open('çıktılar.txt', 'w'):
sys.stdout = f
sys.stdout.write('merhaba zalim dünya')

Gerçi bu sizin bilmediğiniz bir şey değil. Zira siz bunu print() Fonksiyonu konusunu işlerken de görmüştünüz…

sys.stderr

Önceki bölümde gördüğümüz şu kodları tekrar önümüze alalım:

import sys

f = open('çıktılar.txt', 'w')
sys.stdout = f
sys.stdout.write('merhaba zalim dünya')

Bu kodlar, bildiğiniz gibi, çıktı olarak verilmek istenen değerlerin çıktılar.txt adlı bir dosyaya yönlendirilmesini sağlıyor. Ancak kodlarımızı bu şekilde yazdığımızda sadece normal değerler yönlendirilecektir. Mesela çalışma esnasında ortaya çıkan hatalar yine komut ekranına basılmaya devam edecektir:

import sys

f = open('çıktılar.txt', 'w')
sys.stdout = f
sys.stdout.write(1/0)

Bu kodları çalıştırdığınızda, standart çıktı konumu yönlendirilmiş olmasına rağmen, hata mesajı komut satırına basılacaktır:

Traceback (most recent call last):
  File "deneme.py", line 5, in <module>
    sys.stdout.write(1/0)
ZeroDivisionError: division by zero

Çünkü Python’da hata mesajlarının öntanımlı olarak basıldığı yer komut satırıdır. Nasıl çıktıların standart olarak basıldığı yeri teknik olarak ‘standart çıktı konumu’ (Standard Output - stdout) olarak adlandırıyorsak, hataların standart olarak basıldığı yeri de teknik olarak ‘standart hata konumu’ (Standard Error - stderr) olarak adlandırıyoruz.

Tıpkı stdout’u manipüle edebildiğimiz gibi, stderr’i de manipüle edebiliriz:

import sys

f =open('hatalar.txt', 'w')
sys.stderr = f
sys.stderr.write(1/0)

Bu durumda, programımızın işleyişi sırasında ortaya çıkan hatalar hatalar.txt adlı bir dosyaya yönlendirilecektir.

Bu bilgiyi kullanarak şöyle bir kod da yazabiliriz:

import sys

çıktılar = open('çıktılar.txt', 'w')
hatalar = open('hatalar.txt', 'w')
sys.stdout = çıktılar
sys.stderr = hatalar

print('normal çıktı')
print('hata mesajı: ', 1/0)

Bu kodları çalıştırdığınızda, hata mesajı üretmeden başarıyla tamamlanan çıktıların çıktılar.txt adlı dosyaya, hata mesajlarının ise hatalar.txt adlı dosyaya yönlendirildiğini göreceksiniz.

sys.stdin

Python’da üç adet standart konum bulunur:

  1. Standart çıktı konumu - stdout

  2. Standart hata konumu - stderr

  3. Standart girdi konumu - stdin

İlk ikisini zaten görmüştük. Üçüncüsünü de şimdi ele alacağız.

Bildiğiniz gibi Python’da kullanıcıdan veri almak için input() fonksiyonunu kullanıyoruz:

sayı = input('Lütfen bir sayı girin: ')

Bu fonksiyonun görevi, standart girdi konumuna girilen verileri okumaktır. Python’daki standart girdi konumu (genellikle) komut satırı olduğu için, input() fonksiyonu verileri komut satırından okur.

Python’da standart girdi konumunu tutan değişken sys.stdin’dir. Dolayısıyla eğer isterseniz, verileri kullanıcıdan input() fonksiyonu yerine doğrudan sys.stdin niteliği aracılığıyla da alabilirsiniz:

>>> import sys
>>> sys.stdin.read()

Bu komutları verdiğinizde, komut satırı sizden veri almaya hazır hale gelir. Bu şekilde istediğiniz kadar veriyi komut satırına girebilirsiniz. Veri girişini durdurmak istediğinizde ise Windows’ta CTRL+C, GNU/Linux’ta ise CTRL+D tuşlarına basmanız gerekir. Bu şekilde komut satırını terkettiğinizde, girmiş olduğunuz değerler bir karakter dizisi olarak ekrana basılacaktır.

sys.stdin niteliği, bize veri okumak için üç farklı fonksiyon sunar:

  1. sys.stdin.read()

  2. sys.stdin.readline()

  3. sys.stdin.readlines()

read() fonksiyonu birden fazla satır içeren verilerin girilmesine müsaade eder ve çıktı olarak bir karakter dizisi verir:

>>> sys.stdin.read()
(Girdi)
Fırat
Özgül
Adana
(Çıktı)
'Fırat\nÖzgül\nAdana\n'

readline() fonksiyonu tek bir satır içeren verilerin girilmesine müsaade eder ve çıktı olarak bir karakter dizisi verir:

>>> sys.stdin.readline()
(Girdi)
Fırat
(Çıktı)
'Fırat\n'

readlines() fonksiyonu birden fazla satır içeren verilerin girilmesine müsaade eder ve çıktı olarak bir liste verir:

>>> sys.stdin.readlines()
(Girdi)
Fırat
Özgül
Adana
(Çıktı)
['Fırat\n', 'Özgül\n', 'Adana\n']

Gelin isterseniz sys.stdin niteliğinin nasıl kullanılabileceğine ilişkin birkaç örnek verelim:

import sys

with open('kayıtlar.txt', 'w') as kayıtlar:
    while True:
        satırlar = sys.stdin.readline()
        if satırlar.strip() == ':q':
            break
        else:
            kayıtlar.write(satırlar)

Burada kayıtlar.txt adlı bir dosya oluşturduk öncelikle. Daha sonra da readline() fonksiyonu aracılığıyla kullanıcıdan aldığımız bütün verileri bu dosyaya yazdık. Kullanıcının programdan çıkabilmesini sağlamak için de ‘:q’ tuş kombinasyonunu ayarladık. Böylece komut satırından çalışan basit bir metin düzenleyici yazmış olduk!

Tıpkı sys.stdout ve sys.stderr konumlarını değiştirdiğimiz gibi, sys.stdin konumunu da değiştirebiliriz. Böylece verileri komut satırı aracılığıyla değil, mesela bir dosya aracılığıyla alabiliriz.

Aşağıdaki örneği dikkatlice inceleyin:

import sys

f = open('oku.txt')

sys.stdin = f

while True:
    satırlar = sys.stdin.readline()
    if satırlar.strip() == ':q':
        break
    else:
        sys.stdout.write(satırlar)

Bu kodları yazdıktan sonra, bu kodların bulunduğu dizinde oku.txt adlı bir dosya oluşturun. Ardından programınızı çalıştırın. Programınız şu anda sizden veri girmenizi bekliyor. Verileri oku.txt adlı dosyaya gireceksiniz.

oku.txt adlı dosyayı açıp bir şeyler yazın. Veri girerken dosyayı her kaydedişinizde dosya içindeki verilerin komut satırına düştüğünü göreceksiniz. Veri girişini tamamladıktan sonra dosyanın en son satırına ‘:q’ yazıp dosyayı kaydettiğiniz anda da programınız kapanacaktır.

Yorumlar

Önemli Not

Sorularınızı yorumlarda dile getirmek yerine Yazbel Forumunda sorarsanız çok daha hızlı cevap alabilirsiniz.
Belgelerdeki bir hata veya eksiği dile getirecekseniz lütfen yorumları kullanmak yerine Github'da bir konu (issue) açın.
Eğer yazdığınız yorum içinde kod kullanacaksanız kodlarınızı <pre><code> etiketleri içine alın. Örneğin:
        <pre><code class="python">
        print("Merhaba Dünya!")
        </code></pre>