os – az operációs rendszerrel kapcsolatos dolgok

Munka fájlokkal és könyvtárakkal

Könyvtár kilistázása

# File: os_listdir.py

import os

for file in os.listdir("./"):
    print file
# File: os_listdir.out

...
egyedi_pdf_01_nevjegykartya.py
egyedi_teljes_info_processzorrol_rendszerrol.out
egyedi_teljes_info_processzorrol_rendszerrol.py
egyedi_win_halokartya_adatainak_leolvasasa.out
egyedi_win_halokartya_adatainak_leolvasasa.py
egyedi_win_vagolaprol_szoveg_olvasasa.py
...

Az os.listdir használata a könyvtárstruktúra bejárására

# File: os_listdir_fajlrendszerbejaras.py import os # adott konyvtartartalom kilistazasa: for file in os.listdir("."): print file # konyvtartartalom rekurziv bejarasa def index(konyvtar): # mint os.listdir, de bejarja a konyvtarstrukturat tarolo = [konyvtar] fajlok = [] while tarolo: konyvtar = tarolo.pop() for file in os.listdir(konyvtar): fullname = os.path.join(konyvtar, file) fajlok.append(fullname) if os.path.isdir(fullname) and not os.path.islink(fullname): tarolo.append(fullname) return fajlok for file in index("h:\\"): print file

Könyvtárváltások

# File: os_change_dir.py

import os

aktualis_konyvtar = os.getcwd()
print "1", aktualis_konyvtar

# belepes alkonyvtarba
os.chdir("raktar")
print "2", os.getcwd()

# belepes szulo konyvtarba
os.chdir(os.pardir)
print "3", os.getcwd()
# File: os_change_dir.out

1 /var/www/python_lib/examples
2 /var/www/python_lib/examples/raktar
3 /var/www/python_lib/examples

Könyvtár(struktúrák) létrehozása és rekurzív törlése

# File: os_konyvtarak_letrehozasa_es_rekurziv_torlese.py import os, time # itt valojaban harom egymasba agyazott konyvtarletrehozas tortenik, # eloszor teszt, majd azon belul a tobbi! os.makedirs("teszt/tobb/szint") fp = open("teszt/tobb/szint/file", "w") fp.write("Vadkorte, mas neven a vackor") fp.close() print "ellenorizd mit csinalt a program, picit varunk" for i in range(1, 10): print "varunk: ", i time.sleep(1) # letrehozott file torlese os.remove("teszt/tobb/szint/file") # az URES konyvtarstruktura (rekurziv) torlese os.removedirs("teszt/tobb/szint") # egyszeru, nem rekurziv konyvtarletrehozas es torles: os.mkdir("teszt") os.rmdir("teszt") # a nem ures konyvtarakat ez nem torli!

Fájl attribútumok

Fájl tulajdonságok kiolvasása

# File: os_file_attributes.py import os import time file = "index.php" def dump(st): mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime = st print "- size:", size, "bytes" print "- owner:", uid, gid print "- created:", time.ctime(ctime) print "- last accessed:", time.ctime(atime) print "- last modified:", time.ctime(mtime) print "- mode:", oct(mode) print "- inode/dev:", ino, dev # lekerdezzuk a fajlhoz tartozo informaciokat st = os.stat(file) print "stat", file dump(st) # egy nyitott fajl informacioit kerjuk le: fp = open(file) st = os.fstat(fp.fileno()) print "fstat", file dump(st)

# File: os_file_attributes.out stat index.php - size: 4111 bytes - owner: 1000 33 - created: Tue Apr 4 20:57:30 2006 - last accessed: Tue Apr 4 20:57:37 2006 - last modified: Tue Apr 4 20:03:45 2006 - mode: 0100644 - inode/dev: 4194337 777 fstat index.php - size: 4111 bytes - owner: 1000 33 - created: Tue Apr 4 20:57:30 2006 - last accessed: Tue Apr 4 20:57:37 2006 - last modified: Tue Apr 4 20:03:45 2006 - mode: 0100644 - inode/dev: 4194337 777

Némelyik fájl-tulajdonság nem elérhető ha nem Unix platformon fut a program – az inode, dev tulajdonságok minden fájl esetében egyedi Unix-on, de más platformokon véletlenszerű értékeket is felvehetnek, mivel az operációs rendszer nem használja őket, nem rendelkeznek értékkel.

A stat modul számos hasznos állandót és függvényt tartalmaz a stat tuple kezelésére, egy egyszerű példa következik:

Fájl tulajdonságok módosítása

# File: os_modify_file_attributes.py import os import stat, time infile = "teszt/firefox.jpg" outfile = "teszt/out.jpg" # masolatot keszitek az eredeti fajlrol fi = open(infile, "rb") fo = open(outfile, "wb") while 1: s = fi.read(10000) if not s: break fo.write(s) fi.close() fo.close() # lemasolom a fajl 'mode' es 'timestamp' (mod, idobelyeg) tulajdonsagait st = os.stat(infile) os.chmod(outfile, stat.S_IMODE(st[stat.ST_MODE])) os.utime(outfile, (st[stat.ST_ATIME], st[stat.ST_MTIME])) print "eredeti", "=>" print "mode", oct(stat.S_IMODE(st[stat.ST_MODE])) print "atime", time.ctime(st[stat.ST_ATIME]) print "mtime", time.ctime(st[stat.ST_MTIME]) # a kimeneten latszik, hogy a kesobb letrehozott fajl az eredeti idobelyegekkel rendelkezik print "masolat", "=>" st = os.stat(outfile) print "mode", oct(stat.S_IMODE(st[stat.ST_MODE])) print "atime", time.ctime(st[stat.ST_ATIME]) print "mtime", time.ctime(st[stat.ST_MTIME])
# File: os_modify_file_attributes.out

eredeti =>
mode 0666
atime Tue Apr 04 21:26:37 2006
mtime Tue Apr 04 21:26:37 2006
masolat =>
mode 0666
atime Tue Apr 04 21:26:37 2006
mtime Tue Apr 04 21:26:37 2006

Processzek (folyamatok) használata

A system függvény egy új parancsot futtat az aktuális folyamaton belül (nem indít új folyamatot), és megvárja a parancs befejeződését.

Új program indítása, parancskiadás az operációs rendszernek

# File: os_program_futtatasa.py

import os

if os.name == "nt":
    command = "dir"
else:
    command = "ls -l"

os.system(command)
# File: os_program_futtatasa.out

összesen 240
...
-rwxr-xr-x  1 dio www-data  116 2006-02-11 22:38 __builtins__dir.py
-rw-r--r--  1 dio www-data 2918 2006-04-04 21:13 __builtins__.php
-rw-r--r--  1 dio www-data 1006 2006-02-13 09:34 copyright.php
-rw-r--r--  1 dio www-data  556 2006-04-04 21:50 windows.php
...

Figyelem: Mivel az os.system a paraméterét közvetlenül a héjnak továbbítja, ez veszélyes is lehet, ha a paramétert nem ellenőrzöd. Például itt: os.system(“viewer %s” % file) ez az utasítás veszélyes lehet: “sample.jpg; rm -rf $HOME”. Ha bizonytalan vagy az átadott paraméterben, használd az exec vagy a spawn utasítást (lejjebb)

Az exec függvény egy új folyamatot indít, az aktuális helyett. A következő példában a VISZLÁT üzenet soha nem kerül kiírásra:

Új folyamat indítása az os modul felhasználásával

# File: os_uj_folyamat_inditasa.py

import os
import sys

program = "python"
arguments = ["teszt.py"]

print os.execvp(program, (program,) +  tuple(arguments))
print "VISZLAT" # ez a sor soha nem hajtodik vegre, mert feljebb uj folyamat indul.

A Pythonban az exec függvénynek sok fajtája létezik, kicsit eltérő viselkedéssel. A fenti példa az execvp -t használja, ami az elindítandó programot a szabványos útvonalon keresi, és a tupléban kapott paramétereket átadja neki, majd a jelenlegi környezeti változókkal futtatja. Bővebb leírást a Python Library-ban találsz.

Unix alatt úgy is indíthatsz programokat, ha az exec -et kombinálod a fork és a wait utasításokkal. Az előbbi másolatot készít a jelenlegi folyamatról, az utóbbi megvárja a gyermekfolyamat befejeződését.

Új folyamat indítása fork-al (UNIX-on)

# File: os_uj_folyamat_inditasa_fork.py import os import sys def run(program, *args): pid = os.fork() if pid: print pid if not pid: print "nincs pid!" os.execvp(program, (program,) + args) return os.wait()[0] run("python", "teszt.py") print "VISZLAT!"

A fork nulla értékkel tér vissza az új folyamatban (ez a visszatérés, ami először ténylegesen történik!)- és egy nem nulla folyamat azonosítóval a szülő folyamatban. Más szavakkal a “not pid” csak a gyermekfolyamatban lesz igaz.

A fork és a pid Windows-on nem elérhető, a spawn utasítást használhatod helyettük. A spawn jelenleg nem képes a végrehajtható fájlok megkeresésére, ezért ezt neked kell leprogramoznod:

Új folyamat indítása Windows-on

# File: os_uj_folyamat_inditasa_win_spawn.py # Win: itt az uj folyamat vegen a szulo is lefut, ellentetben execvp-vel! import os import string print os.environ["PATH"] # figyelem: ha itt nem talalod a Python konyvtarat, "C:\Python24" ? # az alabbi pelda nem fog lefutni. def run(program, *args): # vegrehajthatok megkeresese for path in string.split(os.environ["PATH"] + ";C:\Python24", os.pathsep): file = os.path.join(path, program) + ".exe" try: return os.spawnv(os.P_WAIT, file, (file,) + args) except os.error: pass raise os.error, "Nem talaltam meg a vegrehajthato fajlt!" run("python", "hello.py") print "VISZLAT!" # az uj folyamat vegeztevel a szulo tovabb fut!

A spawn utasítással háttérben futó programot is indíthatsz. A következő példában egy opcionális mode argumentumot adunk a run függvényhez – ha ez os.P_NOWAIT-ra van beállítva, a program nem várja meg az éppen most elindult folyamat lefutását.

Az alapértelmezett os.P_WAIT beállítással a spawn megvárja az új folyamat befejeződését. Vannak még más beállítási lehetőségek is, például az os.P_OVERLAY, ami az exec működéséhez teszi hasonlóvá a spawn -t, vagy például az os.P_DETACH, ami az új folyamatot a háttérben futtatja, a konzoltól és a billentyűzettől függetlenül.

Új folyamat indítása a háttérben – Windows-on

# File: os_uj_folyamat_inditasa_win_spawn02.py import os import string def run(program, *args, **kw): # a program megkeresese mode = kw.get("mode", os.P_WAIT) for path in string.split(os.environ["PATH"] + ";C:\Python24", os.pathsep): file = os.path.join(path, program) + ".exe" try: return os.spawnv(mode, file, (file,) + args) except os.error: pass raise os.error, "nem talaltam vegrehajthato fajlt" run("python", "teszt.py", mode=os.P_NOWAIT) print "VISZLAT!" # az uj folyamat vegeztevel a szulo tovabb fut!

A démon folyamatok használata

Unix-on fork -al az aktuális folyamatot háttérfolyamattá (démonná) alakíthatod. Ehhez egy másolatot kell készíteni a fő folyamatról, majd ha másolat elkészült, az eredeti futását meg kell szakítani.

Új démon folyamat indítása

# File: os_demon_folyamat_inditasa.py

import os
import time

pid = os.fork()
if pid:
    os._exit(0) #az eredeti megszakitasa

print "demon inditasa"
time.sleep(10)
print "demon futasa veget ert"

Ennél a példánál azért kicsit bonyolultabb valódi démont készíteni. Először a setpgrp függvényt kell használni egy új ‘folyamatok csoportvezetője’ folyamat elkészítésére. Ha ezt nem teszed, jelek érkeznek az (addigra) egymástól független folyamatcsoporthoz, és ez problémákat okozhat a démonodban:

os.setpgrp()

Jó ötlet, ha a felhasználói jogosultság-maszkot eltávolítod, hogy megbizonyosodj arról, hogy a démon által létrehozott fájlok a program által beállított jogosultságokkal jönnek létre:

os.umask(0)

Végül át kell irányítanod a szabványos kimenet és hiba csatornákat (stdout/stderr files), ahelyett hogy bezárnád őket. Ha ezt nem teszed meg, váratlan kivételdobások történhetnek a program futása során, amikor a programod a konzolra akar írni a szabványos kimeneten vagy a hibacsatornán át:

class NullDevice:
    def write(self, s):
        pass

sys.stdin.close() sys.stdout = NullDevice() sys.stderr = NullDevice()

Máskén mondva a Python print és a C nyelv printf/fprintf utasítása nem fogja megszakítani a programod futását, ha a szabványos kimeneteket a NULL eszközre irányítottad – viszont a sys.stdout.write() IOError kivételt fog dobni, ha a program démonként fut, de az előtérben futtatva ez az utasítás rendben fog működni.

Egyszóval az _exit() függvényt használtuk a példában az aktuális folyamat megszakítására. A sys.exit() -el ellentétben ez akkor is működni fog, ha a hívó elkapja a SystemExit kivételt:

Kilépés az aktuális processzből az os modul felhasználásával

# File: os_kilepes_aktualis_folyamatbol.py import os import sys try: sys.exit(1) except SystemExit, value: print "sys.exit() elfoghato!!" print "Elfogva exit(%s)" % value try: print "os._exit() nem elfoghato" os._exit(2) except SystemExit, value: print "elfogva _exit(%s)" % value print "szia!"
# File: os_kilepes_aktualis_folyamatbol.out

sys.exit() elfoghato!!
Elfogva exit(1)
os._exit() nem elfoghato

Fájlok kiterjesztésének cseréje

A munkahelyemen le kellett cserélni pár fájl végződését, ez a programocska lett belőle

# File: os_kiterjesztes_cserelo.py

import glob, os

# .c00 vegzodesu fajlokat akartam .ps-re cserelni.

for eredeti_filenev in glob.glob(".\\*.c00"):
    uj_filenev = eredeti_filenev[:-4] + ".ps"
    print uj_filenev
    os.rename(eredeti_filenev, uj_filenev)

Post Comments

You must be logged in to post a comment.