http://harp.pythonanywhere.com/python_doc/tutorial/index.html
Fontos, hogy az importálás során az
import os
alakot használd,from os import *
alakot.Ez megóv attól, hogy az os.open()
függvény elfedje (és használhatatlanná tegye) a beépített open()
függvényt, ami teljesen másképp működik.
Az os modul nagyon sok függvényt tartalmaz, melyek az operációs rendszerrel kommunikálnak.
Például a beépített dir()
és help()
függvények is sokat segíthetnek.
A mindennapi fájl- és könyvtár-műveletekhez az shutil modul magasszintű, könnyen használható felületet nyújt.
import os
import types
os.system('time 10:34') # FIGYELEM: átállítottuk a rendszer óráját!
print('kész 1')
print('A pontos idő : ', os.system('time'))
print('Az aktuális könyvtár : ', os.getcwd()) # Az aktuális könyvtár nevét adja vissza.
os.chdir(r'c:\Users\User\Documents\mintak\jupiter\kl\okt') # és itt könyvtárar váltottunk.
print('kész 2')
print(dir(os)) ## kilistázza az összes függvényt, ami az 'os' modulban található
print(help(os)) ## egy nagyon részletes manual oldalt generál a modulok dokumentációs karakterláncából
# print all types defined in the `types` module
print(dir(types))
kész 1 A pontos idő : 1 Az aktuális könyvtár : C:\Users\User\Documents\mintak\jupiter\kl\okt kész 2
import shutil
shutil.copyfile('eles.db', 'mentes.db') ## állomány (biztonsági) mentése (másolat)
shutil.move('/build/eles', 'mentes_konyvtar') ## tartalom átmozgatása
## Pyton filek kilistázása
import glob
print(glob.glob('*.py'))
['csvmagic.py', 'first.py', 'mprun_demo.py']
A programoknak gyakran fel kell dolgozniuk a parancssori paramétereiket.
Ezek a paraméterek a sys modul argv attribútumában tárolódnak, listaknént.
import sys
print(sys.argv)
['C:\\Users\\User\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py', '-f', 'C:\\Users\\User\\AppData\\Roaming\\jupyter\\runtime\\kernel-5c7d07bb-366b-4031-b070-d3961d9a97c6.json']
A sys modul szintén rendelkezik stdin, stdout, és stderr attribútummal.
Ez utóbbi használatos figyelmeztetések és hibaüzenetek láthatóvá tételére – például akkor, amikor a stdout át van irányítva, mondjuk egy fájlba.
A legrövidebb út egy program megszakítására a sys.exit() utasítás.
import sys
sys.stderr.write('Figyelem probléma lépett fel\n') ## error output csatornára kiírás
sys.exit() # A futás megszakításása
Figyelem probléma lépett fel
An exception has occurred, use %tb to see the full traceback.
SystemExit
C:\Users\User\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3334: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
A re modul segítségével reguláris kifejezéseket használhatunk szövegfeldolgozásra.
Összetett illeszkedési és módosító szabályokat határozhatunk meg.
A reguláris kifejezések rövid, tömör megoldást kínálnak:
import re # minden b vagy B-vel kezdődő szót kigyüjtünk:
print(re.findall(r'\b[bB][a-z*]*', r'aki belemegy, hogy befizeti a bírságot az nem biztos, hogy nem Balf**sz'))
print(re.sub(r'(\b[a-z]+) \1', r'\1', 'sok a a van a a szövegben b b béből pedig c c kevéss'))
# sok a van a szövegben b béből pedig c kevéss
print('Kecskeméti Pálinka'.replace('Pálinka', 'Lajos'))
## Kecskeméti Lajos
['belemegy', 'befizeti', 'b', 'biztos', 'Balf**sz'] sok a van a szövegben b béből pedig c kevéss Kecskeméti Lajos
A math modulon keresztül érhetőek el a háttérben működő C függvények, melyekkel lebegőpontos műveleteket végezhetünk
import math
print(math.cos(math.pi / 4.0))
print('-----')
print(math.log(1024, 2))
0.7071067811865476 ----- 10.0
import random
print('gyümölcs : ', random.choice(['alma', 'korte', 'banan', 'szilva'])) ## Véletlen szerű választás a listából
print('lotto1 : ', random.sample(range(90), 5)) # ismetles nelkuli mintavetel
print('véletlen szám :', random.random()) # random float
print('lotto2 : ', random.randrange(90)+1) # véletlen egész szám kiválasztása 1-90ig terjedő tartományban
gyümölcs : szilva lotto1 : [75, 9, 2, 77, 80] véletlen szám : 0.5749922024904971 lotto2 : 27
Több modul is van, amely lehetővé teszi az Internet elérését, és különböző protokollok használatát.
A két legegyszerűbb : az urllib + requests –> adatfogadás url címekről, az smtplib -> levelet küldhetünk
import requests
import urllib
link = "https://klajosw.blogspot.com/"
f = urllib.request.urlopen(link)
myfile = f.read() ##
print((myfile[:109])) ## <class 'bytes'>
f.close()
b"<!DOCTYPE html>\n<html class='v2' dir='ltr' lang='hu'>\n<head>\n<link href='https://www.blogger.com/static/v1/wi"
import smtplib
server = smtplib.SMTP('localhost')
server.sendmail('klajosw@gmail.com', 'mierdekel@gmail.com',
"""To: klajosw@gmail.com
From: mierdekel@gmail.com
Szevasz! Eljutottal a nyaralásod vegere.
""")
server.quit()
A datetime modul biztosít osztályokat a dátumok és az időpontok manipulálására – egyszerűbbeket és összetettebbeket is.
A dátum- és az idő- aritmetikai műveletek támogatottak – a középpontban a kimenet formázása és módosítása áll.
A modul támogatja azokat az objektumokat is, amelyek kezelni tudják az időzónákat.
# a dátumok könnyen létrehozhatóak és formázhatóak:
from datetime import date
most = date.today()
print(most)
print(most.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B."))
# a dátumok támogatják a naptári műveleteket:
szuletesnap = date(1962, 3, 14)
kor = most - szuletesnap
print(kor.days) # days = napok, itt az eltelt napok szamat jelenti
print('hét : ', kor.days / 7) # az eltelt hetek szamat jelenti
print(dir(kor)) # milyen belső függvények érhetőek el
2020-02-02 02-02-20. 02 Feb 2020 is a Sunday on the 02 day of February. 21144 hét : 3020.5714285714284 ['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', 'days', 'max', 'microseconds', 'min', 'resolution', 'seconds', 'total_seconds']
import datetime
kl_today = datetime.date.today()
print('ma van : ',kl_today)
kl_now = datetime.datetime.now()
print('most van : ',kl_now)
kl_year = datetime.date(2020, 1, 1)
print('Új év : ', kl_year)
ma van : 2020-02-02 most van : 2020-02-02 20:36:46.783317 Új év : 2020-01-01
from datetime import datetime, timedelta
kl_now = datetime.now()
szulinap = datetime(1962, 3, 14)
delta = kl_now - szulinap
print('Hány napos vagyok : ', delta)
Hány napos vagyok : 21144 days, 20:39:39.746807
Az elterjedtebb archiváló és tömörítő formátumok közvetlenül támogatottak, a következő modulokban: zlib, gzip, bz2, zipfile, and tarfile.
import zlib
s = 'Nezzünk egy szöveget és próbáljuk betomoríteni'
s = 'Nezzunk egy szoveget es probaljuk betomoriteni'
print('STR1 :', len(s))
print('STR2 :', (s))
print('STR3 :', s.encode('utf-8'))
## t = zlib.compress(bytes(s))
t = zlib.compress(str.encode(s))
bytes
print('STR2 :', (t))
s = str(zlib.compress(s.encode('utf-8')))
print('STR1 :', len(s))
#print('ZIP2 :', len(t))
#print('DZIP :', zlib.decompress(t))
#print('CRC1 : ', zlib.crc32(s))
print('kész')
STR1 : 46 STR2 : Nezzunk egy szoveget es probaljuk betomoriteni STR3 : b'Nezzunk egy szoveget es probaljuk betomoriteni' STR2 : b'x\x9c\xf3K\xad\xaa*\xcd\xcbVHM\xafT(\xae\xca/KMO-QH-V((\xcaOJ\xcc\xc9*\xcdVHJ-\xc9\xcf\xcd/\xca,I\xcd\xcb\x04\x00\xa2\x88\x12\x05' STR1 : 132 kész
Néhány Python programozó komoly érdeklődést mutatott a különböző probléma- megoldások teljesítményének összehasonlítása iránt.
A Pythonban található egy mérőeszköz, amely azonnali választ ad ezekre a kérdésekre.
Például használhatunk tuple becsomagolást és kicsomagolást a megszokott paraméter-átadás helyett.
A timeit modul gyorsan demonstrál egy egyszerű teljesítmény mérést:
## A timeit modul apró kódrészletek végrehajtási idejének mérésére szolgál.
## Ezzel ellentétben a profile és a pstats modulok nagyobb kódrészletek
## futási-idő kritikus részeinek meghatározására szolgál.
## Betöltése a modulnak
from timeit import Timer
print('Time 1 : ', Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()) ## változó csere 1 verzio
print('Time 2 : ',Timer('a,b = b,a', 'a=1; b=2').timeit()) ## változó csere 2 verzio (pythonic)
Time 1 : 0.02424119999989216 Time 2 : 0.022523900000010144
A jóminőségű programok fejlesztésnek egyik elmélete az, hogy minden függvényhez próbaadatokat, teszteket írunk – majd a fejlesztési folyamat során ezeket gyakran lefuttatjuk - így azonnal kiderül, ha a várttól eltérően viselkedik a program.
A doctest
modul tartalmaz olyan eszközöket, amelyekkel modulokat vizsgálhatunk, és a program dokumentációs karakterláncába ágyazott teszteket futtathatunk le.
A teszt létrehozása olyan egyszerű, mint kivágni és beilleszteni egy tipikus függvényhívás során bejövő-keletkező adatokat.
Ez a lehetőség elősegíti a jobb dokumentáltságot, hiszen a felhasználónak rögtön függvényhívási példát mutathatunk – továbbá ellenőrizhetővé teszi a doctest
modulnak, hogy a kód a dokumentációval összhangban van-e.
def atlag(ertekek):
"""Listában átadott számok számtani közepét határozza meg a függvény.
Használata:
print(atlag([20, 30, 70]))
Eredmény:
40.0
"""
return sum(ertekek) / len(ertekek)
import doctest
doctest.testmod() # a beágyazott tesztet automatikusan kipróbálja.
TestResults(failed=0, attempted=0)
---
A `unittest` modul kicsit bonyolultabb, mint a doctest modul – viszont több átfogó
tesztkészlet kezeléséről gondoskodik, egy különálló fájlban:
----
import unittest
class StatisztikaiFuggvenyekTesztelese(unittest.TestCase):
def atlag_tesztelese(self):
self.assertEqual(atlag([20, 30, 70]), 40.0)
self.assertEqual(round(atlag([1, 5, 7]), 1), 4.3)
with self.assertRaises(ZeroDivisionError):
atlag([])
with self.assertRaises(TypeError):
atlag(20, 30, 70)
unittest.main() # A parancssorból történő hívás lefuttatja a teszteket.
E ====================================================================== ERROR: C:\Users\User\AppData\Roaming\jupyter\runtime\kernel-11129c68-5bb4-44df-b33d-19c95b05a471 (unittest.loader._FailedTest) ---------------------------------------------------------------------- AttributeError: module '__main__' has no attribute 'C:\Users\User\AppData\Roaming\jupyter\runtime\kernel-11129c68-5bb4-44df-b33d-19c95b05a471' ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (errors=1)
An exception has occurred, use %tb to see the full traceback. SystemExit: True
C:\Users\User\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3334: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D. warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
A Python filozófiája: “elemekkel együtt”. A legjobban ez úgy látszik, ha észrevesszük nagyszámú moduljainak - csomagjainak kifinomultságát, összetettségét.
Az xmlrpclib
és a SimpleXMLRPCServer
modulok a távoli eljáráshívásokat egyszerű műveletté teszik számunkra. A neveik ellenére nincs közvetlen XML tudásra szükség.
Az email
csomag egy könyvtár az elektronikus levelek kezelésére – beleértve a MIME és más RFC 2822-alapú üzeneteket is.
Eltérően az smtplib
és poplib
moduloktól, melyek azonnali levélküldést és fogadást valósítanak meg, az email csomag teljes eszközkészlettel rendelkezik összetett üzenet-struktúrák felépítéséhez és dekódolásához – a csatolt állományokat is beleértve. Továbbá tartalmazza az Interneten használt kódoló és fejléc protokollokat.
Az xml.dom
és az xml.sax
csomagok nagyon jól használhatók az elterjedt adat-cserélő formátumok kezelésére, értelmezésére és feldolgozására
Ugyanúgy a csv
modul támogatja a csv formátum közvetlen írását és olvasását. Mindent egybevéve ezek a modulok és csomagok remekül leegyszerűsíti a Python programok és más alkalmazások közötti adatcserét.
A kultúrális tulajdonságok beállíthatók és támogatottak számos modulban, például: gettext
, locale
, és a codecs
csomagban is.
A repr()
függvény lehetővé teszi a nagyméretű, mélyen egymásba ágyazott adatszerkezetek rövid, áttekinthető kijelzését.
A pprint
modullal finoman szabályozhatod beépített és a felhasználó által definiált objektumok megjelenítését
– úgy, hogy az az értelmező számára továbbra is feldolgozható marad. Amikor az eredmény nem fér el egy sorban,
egy “csinos nyomtató” sortöréseket és behúzásokat ad a kimenethez, hogy az jól olvasható leyen.
A textwrap
modullal szövegblokkokak jeleníthetünk meg adott szélességű blokkban.
print('repr : ', repr(set('elkelkaposztastalanitottatok')))
print('-----------------------------------')
import pprint
t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]]
pprint.pprint(t, width=30)
print('-----------------------------------')
import textwrap
doc = """The wrap() method is just like fill() except that it returns
a list of strings instead of one big string with newlines to separate
the wrapped lines."""
print(textwrap.fill(doc, width=40))
repr : {'s', 'o', 'e', 'a', 'k', 'l', 'p', 'i', 'n', 'z', 't'} ----------------------------------- [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]] ----------------------------------- The wrap() method is just like fill() except that it returns a list of strings instead of one big string with newlines to separate the wrapped lines.
A locale
modul a különböző kultúrákhoz kötődő egyedi adatformázásokhoz fér hozzá
a locale format
funkciójának grouping
(csoportosítás, a következő példában helyiérték)
tulajdonsága közvetlenül biztosítja az adott kultúrának megfelelő szám-kijelzést.
import locale
locale.setlocale(locale.LC_ALL, 'English_United States.1252')
conv = locale.localeconv() # get a mapping of conventions
x = 1234567.8
locale.format("%d", x, grouping=True)
locale.format("%s %.*f", (conv['currency_symbol'], conv['int_frac_digits'], x), grouping=True)
C:\Users\User\Anaconda3\lib\site-packages\ipykernel_launcher.py:8: DeprecationWarning: This method will be removed in a future version of Python. Use 'locale.format_string()' instead. C:\Users\User\Anaconda3\lib\site-packages\ipykernel_launcher.py:10: DeprecationWarning: This method will be removed in a future version of Python. Use 'locale.format_string()' instead. # Remove the CWD from sys.path while we load stuff.
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-14-30af6eec32b3> in <module> 8 locale.format("%d", x, grouping=True) 9 ---> 10 locale.format("%s %.*f", (conv['currency_symbol'], conv['int_frac_digits'], x), grouping=True) ~\Anaconda3\lib\locale.py in format(percent, value, grouping, monetary, *additional) 254 if not match or len(match.group())!= len(percent): 255 raise ValueError(("format() must be given exactly one %%char " --> 256 "format specifier, %s not valid") % repr(percent)) 257 return _format(percent, value, grouping, monetary, *additional) 258 ValueError: format() must be given exactly one %char format specifier, '%s %.*f' not valid
A string modulban található egy nagyon hasznos osztály, a Template
.
Ez lehetőséget ad a végfelhasználóknak sablon-szövegek szerkesztésére.
A szövegbe adatmezőket a $ jellel helyezhetünk el, melyek mellé kapcsos zárójelbe Python változóneveket kell írni (ez számot, betűt és alsóvonás karaktert tartalmazhat).
A kapcsos zárójelpárra akkor van szükség, ha nem önálló szó a beillesztett adat, például lent a ‘Peternek’ szó lesz ilyen egyébként a zárójelpár elhagyható.
Egyszerű $ jelet így írhatsz: $$
A substitute()
medódus KeyError
kivételt dob, ha az adatmezőkben megadott változónevet a paraméterként átadott szótárban, vagy kulcsszavas paraméterekben nem találja.
Elképzelhető olyan helyzet, hogy valamelyik változónév (vagy kulcs, ha szótárról van szó) hiányzik - ilyenkor a safe_substitute()
metódust érdemes használni, ami a hiányzó adatoknál az adatmezőt változatlanul hagyja
from string import Template
t = Template('${nev}nek kuldunk 10$$-t, hogy $cselekedet.')
t.substitute(nev='Peter', cselekedet='csizmat vegyen')
'Peternek kuldunk 10$-t, hogy csizmat vegyen.'
# ez a pelda nem fut le, hianyzik $owner
t = Template('Return the $item to $owner.')
d = dict(item='unladen swallow')
t.substitute(d)
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-18-30c92896ae78> in <module> 2 t = Template('Return the $item to $owner.') 3 d = dict(item='unladen swallow') ----> 4 t.substitute(d) 5 ~\Anaconda3\lib\string.py in substitute(*args, **kws) 130 raise ValueError('Unrecognized named group in pattern', 131 self.pattern) --> 132 return self.pattern.sub(convert, self.template) 133 134 def safe_substitute(*args, **kws): ~\Anaconda3\lib\string.py in convert(mo) 123 named = mo.group('named') or mo.group('braced') 124 if named is not None: --> 125 return str(mapping[named]) 126 if mo.group('escaped') is not None: 127 return self.delimiter KeyError: 'owner'
## ez a pelda lefut, pedig hianyzik $owner:browse confirm saveas
t = Template('Return the $item to $owner.')
d = dict(item='unladen swallow')
t.safe_substitute(d)
'Return the unladen swallow to $owner.'
A Template alosztály egyedi határolójelet is tud használni. Például egy tömeges fájl-átnevező funkció esetében (pl. fénykép-karbantartó programnál) az adatmezők jelzésére használhatod a százalék jelet is, az aktuális dátum, a kép sorszáma, vagy a fájl formátumának jelzése esetén.
import time, os.path
photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg']
class BatchRename(Template):
delimiter = '%'
fmt = raw_input('Add meg az atnevezes modjat: (%d-datum %n-fajl_sorszama %f-fileformatum): ') ## Ashley_%n%f
t = BatchRename(fmt)
date = time.strftime('%d%b%y')
for i, filename in enumerate(photofiles):
base, ext = os.path.splitext(filename)
newname = t.substitute(d=date, n=i, f=ext)
print('%s --> %s' % (filename, newname))
A szövegsablonok másik felhasználási lehetősége a többféle kimeneti formátumot támogató programokban van. Itt a vezérlési logika a kimenettől el van választva – A kimeneti fájl felépítése más XML fájloknál, szövegfájloknál, vagy html kimenet esetében, viszont az adattartalom értelemszerűen megegyezik.
A struct
modulban található a pack()
és az unpack()
függvények, melyekkel változó hosszúságú bináris adatblokkokat kezelhetsz.
A következő példa bemutatja a ZIP fájlok fejléc információinak feldolgozását (a "H" és az "L" kódcsomag jelképezi a két és négybájtos előjel nélküli számokat):
import struct
data = open(r'c:\Users\User\Downloads\Feladatcsomag10.zip', 'rb').read()
start = 0
for i in range(3): # megnezzuk az elso harom fajl fejlecet
start += 14
fields = struct.unpack('LLLHH', data[start:start+16])
crc32, comp_size, uncomp_size, filenamesize, extra_size = fields
start += 16
filename = data[start:start+filenamesize]
start += filenamesize
extra = data[start:start+extra_size]
print(filename, hex(crc32), comp_size, uncomp_size)
start += extra_size + comp_size # tovabblepes a kovetkezo fejlechez
b'Feladatcsomag10/' 0x0 0 0 b'Feladatcsomag10/A Sapphire HD 7870 OC.html' 0x32af6be9 6314 34607 b'Feladatcsomag10/A Sapphire HD 7870 OC_elemei/' 0x0 0 0
A szálkezeléssel lehet az egymástól sorrendileg nem függő folyamatokat párhuzamossá tenni.
A szálakkal egyidőben fogadhatjuk a program felhasználójának utasításait, miközben a háttérben a program egy feladaton dolgozik - a két folyamat (kommunikáció, és háttérben munka) egymással párhuzamosan fut.
A következő kód bemutatja a threading modul magasszintű használatát, ami egy külön háttérfolyamatot indít, miközben a program fut tovább.
A többszálú programok egyik legfontosabb feladata azon szálak működésének koordinálása, melyek megosztott adatokon, vagy közös erőforrásokon dolgoznak. (pl. mi történik ha két szál egyidőben akar egy fájlt írni?)
A Threading modul több szinkronizációs elemet tartalmaz – ilyen a zárolás, az eseménykezelés, a feltételes változók és a szemaforok.
Igaz ugyan, hogy ezek hatékony eszközök – ám előfordulhatnak kisebb tervezési hibák is, melyek nehezen megismételhetők, és nehezen kinyomozhatók. Mivel a szálak egymástól függetlenül futnak, még végrehajtásuk sorrendje sem biztos - emiatt előfordulhat, hogy a program nem ugyanúgy viselkedik, ha egymás után többször lefuttatjuk – így a hibakeresés is nehezebbé válik.
A szálak koordinálására azt javasoljuk, hogy az erőforrások elérését egy szál biztosítsa, és használd a Queue modult a többi szálból érkező kérések kezelésére.
Ha egy programban a szálak közötti kommunikációt a Queue objektumokkal biztosítod, a program koordinálásának megtervezése egyszerűbb, olvashatóbb és megbízhatóbb lesz.
import threading, zipfile
class AsyncZip(threading.Thread):
def __init__(self, infile, outfile):
threading.Thread.__init__(self)
self.infile = infile
self.outfile = outfile
def run(self):
f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED)
f.write(self.infile)
f.close()
print('Kesz a zip tomoritese ennek a fajlnak: ', self.infile)
background = AsyncZip('nfl_height_weight.csv', 'myarchive.zip')
background.start()
print('A foprogram tovabb fut az eloterben.')
background.join() # Varakozas a hattermuvelet befejezesere
print('A foprogram megvarja, hogy a hattermuvelet befejezodjon.')
A foprogram tovabb fut az eloterben. Kesz a zip tomoritese ennek a fajlnak: nfl_height_weight.csv A foprogram megvarja, hogy a hattermuvelet befejezodjon.
A logging modul egy összetett, finoman beállítható naplózó rendszert tartalmaz.
A legegyszerűbb esetben a naplózandó üzenetek fájlba, vagy a sys.stderr (szabványos hibakimenetre) - küldhetők:
Alapértelmezés szerint az információs és debug üzenetek elfojtottak, és a kimenet a szabványos hiba csatornára kerül.
A kimenet célja más is lehet, például email, datagram, socket vagy akár egy HTTP szerver. Az új szűrők az üzenet prioritásától függően más-más kimenetre terelhetik a naplózandó üzenetet.
A prioritások: DEBUG, INFO, WARNING, ERROR, és CRITICAL.
A naplózó rendszer közvetlenül a Pythonból is beállítható, vagy használhatsz konfigurációs fájlt, s így a programból való kilépés nélkül megváltoztathatod a naplózás beállításait.
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
WARNING:root:Warning:config file server.conf not found ERROR:root:Error occurred CRITICAL:root:Critical error -- shutting down
A memóriakezelést a Python automatikusan végzi (hivatkozásszámlálás a legtöbb objektum esetében, és szemétgyűjtés).
Az utolsó objektum-hivatkozás megsemmisülése után az elfoglalt memória felszabadul.
Ez az automatizmus a legtöbb esetben jó és hasznos, de néha szükség van az objektumok követésére mindaddig, amíg használatban vannak.
Érdekes, hogy éppen ez a követés az, ami a hivatkozásokat állandóvá teszi (nem szűnnek meg).
A weakref
modulban olyan eszközök vannak, amelyekkel úgy lehet nyomon követni az objektumokat,
hogy a nyomkövetéssel nem hozol létre újabb hivatkozást az objektumra.
Amikor az objektumot már senki nem használja, automatikusan törlődik a weakref (gyenge referencia) táblából, és a weakref objektum erről értesítést kap.
A tipikus programok tároló objektumokat tartalmaznak, melyek létrehozása erőforrásigényes.
---
import weakref, gc
class A:
def __init__(self, ertek):
self.ertek = ertek
def __repr__(self):
return str(self.ertek)
a = A(10) # hivatkozas letrehozasa
d = weakref.WeakValueDictionary()
d['primary'] = a # itt nem keletkezik hivatkozas
d['primary'] # ha az objektum meg letezik, visszaadja az erteket
del a # toroljuk az egyetlen hivatkozast
gc.collect() # a szemetgyujtest azonnal lefuttatjuk
d['primary'] # ez a bejegyzes automatikusan megszunt, nem kell kulon torolni
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-28-08a65bf9f7b7> in <module> 15 gc.collect() # a szemetgyujtest azonnal lefuttatjuk 16 ---> 17 d['primary'] # ez a bejegyzes automatikusan megszunt, nem kell kulon torolni ~\Anaconda3\lib\weakref.py in __getitem__(self, key) 135 if self._pending_removals: 136 self._commit_removals() --> 137 o = self.data[key]() 138 if o is None: 139 raise KeyError(key) KeyError: 'primary'
A legtöbb adatstruktúrának szüksége van a beépített lista típusra.
Néha előfordul, hogy a listák egy másfajta megvalósítására van szükség, az eredeti listáktól eltérő viselkedéssel.
Az array modulban található array() objektum hasonlít azokhoz a listákhoz, melyek csak hasonló adat-típusokat tárolnak, de ezt a tárolást sokkal tömörebben végzi.
A következő példában egy számokból álló tömböt láthatunk, ahol a számok mint két bájtos előjel-nélküli bináris számként tárolódnak (típuskód: "H") – ellentétben a hagyományos Python int (egész szám) objektumokból álló listákkal, ahol minden bejegyzés 16 bájtot használ.
from array import array
a = array('H', [4000, 10, 700, 22222])
print('sum : ', sum(a))
print('a[] : ', a[1:3])
sum : 26932 a[] : array('H', [10, 700])
A collections modulban lévő deque() objektum egy – a listához hasonló típus – viszont gyorsabban tud új elemet felvenni a lista végére és elemet kiemelni a lista elejéről.
Hátránya viszont, hogy a keresésben lassabb - nehézkesebb, mint a hagyományos lista.
Ez az objektumtípus hasznos várakozási sorok, listák megvalósítására és mélységi keresés esetén.
Ráadásul az Alapkönyvtár más eszközöket is tartalmaz, például a bisect modult, ami rendezett listák módosítására szolgál.
from collections import deque
d = deque(["task1", "task2", "task3"])
d.append("task4")
print("Handling", d.popleft())
unsearched = deque(["task1", "task2", "task3"])
def breadth_first_search(unsearched):
node = unsearched.popleft()
for m in gen_moves(node):
if is_goal(m):
return m
unsearched.append(m)
breadth_first_search(unsearched)
print(unsearched)
Handling task1
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-37-45543bd9f0d9> in <module> 13 unsearched.append(m) 14 ---> 15 breadth_first_search(unsearched) 16 print(unsearched) <ipython-input-37-45543bd9f0d9> in breadth_first_search(unsearched) 8 def breadth_first_search(unsearched): 9 node = unsearched.popleft() ---> 10 for m in gen_moves(node): 11 if is_goal(m): 12 return m NameError: name 'gen_moves' is not defined
import bisect
scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')]
bisect.insort(scores, (300, 'ruby'))
print(' scores : ', scores)
scores : [(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]
A heapq
modulban található függvényekkel megvalósíthatók a hagyományos listákon alapuló adathalmazok kezelése.
A legalacsonyabb értékű bejegyzés mindig a nulla pozícióba kerül.
Ez hasznos, ha a programodnak gyakran kell elérnie a lista legkisebb elemét, de nem akarod a listát teljes mértékben rendezni:
from heapq import heapify, heappop, heappush
data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
heapify(data) # átrendezi a listát
heappush(data, -5) # új elemet ad a listába
[heappop(data) for i in range(3)] # kilistázza a három legkisebb elemet.
[-5, 0, 1]
A decimal modulban található a Decimal adattípus, lebegőpontos számításokhoz.
A beépített float típushoz képest, amely a bináris lebegőpontos számításokhoz készült, az új osztály nagyon sokat segít pénzügyi programoknál (és ott, ahol véges decimális ábrázolást használnak, a pontosság ellenőrzésével, a törvényeknek vagy a szabályoknak megfelelő kerekítés használatával, a fontos számjegyek nyomkövetésével – vagy olyan programoknál, ahol a felhasználó kézzel végzett számításokhoz akarja hasonlítani a végeredményt.
Például számítsuk ki az 5%-os adóját egy 70 centes telefonköltségnek, ami különböző eredményt ad decimális és bináris lebegőpontos számítás használata esetén.
A különbség fontos lesz, ha a kerekítés a legközelebbi centhez történik.
A Decimal osztály teljesen pontosan ábrázolja a maradékos osztást, és az egyenlőségtesztelést, ami a bináris lebegőpontos ábrázolás esetén helytelen eredményre vezet.
A Decimal osztály eredménye egy lezáró nullát tartalmaz, automatikusan négy számjegyűen kerül ábrázolásra, a 2*2 számjegyű (tizedesjegyek) szorzás eredményeképp. A Decimal ugyanolyan matematikát használ, mint amit a papíron végzett számolás, és elkerüli azokat a kérdéseket, amikor a bináris lebegőpontos számítás nem tud abszolút pontosan ábrázolni decimális mennyiségeket.
from decimal import *
print(Decimal('0.70') * Decimal('1.05'))
print(Decimal("0.7350"))
print(Decimal('1.00') % Decimal('.10'))
print(Decimal("0.00"))
print(sum([Decimal('0.1')]*10) == Decimal('1.0'))
print(sum([0.1]*10) == 1.0)
## A decimal modulban a számítások pontosságát szükség szerint beállíthatod:
getcontext().prec = 36
print(Decimal(1) / Decimal(7))
print(Decimal("0.142857142857142857142857142857142857"))
0.7350 0.7350 0.00 0.00 True False 0.142857142857142857142857142857142857 0.142857142857142857142857142857142857