PythonGuide/InputOutput
من PFWiki
محتويات |
التعامل مع الملفات
هنتكلم فى الفصل دا عن التعامل مع ال files وتحديدا ال IO اختصارا ل Input/Output ال file type بيعبر عن صف مسئول عن التعامل مع الملفات (ممكن يكون سوكيت او غيره بما ان كل شئ عبارة عن file)
فى اكثر من طريقة لإنشاء file object ودا عن طريق open او file class open هتعمل ريترن بfile object وهى معرفة كالتالى open(name, mode, buffering)
حيث name هو مسار الملف mode هو بيعبر عن حالة الوصول (الملف مفتوح للقراءة ، للكتابة ، للإضافة ؟) الإفتراضى هو r للقراءة
r → قراءة فقط w → كتابة فقط (بيتم محو كل البيانات الموجودة) a → للإضافة من عند النهاية ،مع عدم محو البيانات r+ → قراءة وكتابة w+ → كتابة وقراءة اى من ال modes السابقة اذا لحقته ب b اختصارا ل binary سيتم التعامل مع binary read, binary write, .. etc
ال buffering لتحديد هل سيتم عمل اى buffering فى حال التعامل مع الملف، الإفتراضى هو -1 (بيتم النقل لنظام التشغيل)
.close()
لغلق ال file object
.read(num=None)
بتقوم بقراءة عدد معين من البايتات وفى حال عدم تحديده بيتم قراءة الملف بكامله
.readline()
قراءة سطر واحد
.readlines()
قراءة كل السطور (على صورة list)
.tell()
بتخبرنا بالمكان الحالى
.fseek(offset, whence=0)
بتنقل المكان الحالى الى offset معين بعد ال whence whence ربما تكون 0 (اى بداية الملف ) او1 (المكان الحالى) او 2 (نهاية الملف) عندنا ملف سميناه iotest.xcd فيه التالى 0123456789
.write(s)
يقوم بكتابة s فى الملف
.writelines(seq_of_strings)
يقوم بكتابه كل عناصر seq_of_strings فى الملف --كقيامك بإستدعاء write على كل عنصر فى هذه ال sequence
.fileno()
الحصول على File Descriptor خاص بال file
.flush()
لتأكيد نقل الbuffer الداخلى كله على الملف
.nameللحصول على مسار الملف
.modeللحصول على ال access mode
.encodingللحصول على الإنكودينج
.closedللتحقق من تحقق اغلاق المسار
FNAME="iotest.xcd" txt=""" line 1 line 2 line 3 line 4 line 5 line 6 line 7 some text yada yada yada! """ f=open(FNAME, "w") print f.fileno() print f.name print f.mode print f.closed f.write(txt) f.close() print f.closed
فى المثال السابق قمنا بفتح ملف iotext.xcd للكتابة، وكتبنا فى داخله محتويات المتغير txt الناتج
3 iotest.xcd w False True
القراءة
f=open(FNAME, "r") lines=f.readlines() for line in lines: print "LINE = > ", line, #avoid printing a new line. الناتج LINE = > LINE = > line 1 LINE = > line 2 LINE = > line 3 LINE = > line 4 LINE = > line 5 LINE = > line 6 LINE = > line 7 LINE = > some text LINE = > yada yada yada!
معاملات سطر الأوامر لبرنامجك
بكل بساطة مش هتحتاج غير ال argument vector ودى موجودة فى ال sys.argv لو فاكر int main(int argc, char** argv){
} فللوصول لل argv استخدم argv الموجودة بال sys module وللحصول على عددهم استخدم len(argv)
striky@striky-desktop:~$ python myecho.py hello world 123 "78 yay" Number of arguments: 5 myecho.py hello world 123 78 yay
myecho.py #!bin/python from sys import argv # arguments vector. print "Number of arguments: ", len(argv) for arg in argv: print arg
More IO stuff
فى عندنا 2 modules مهمين هما os, os.path ضيفهم كالتالى
import os import os.path as op
os.uname()
بتعيد tuple مكونة من (sysname, nodename, release, version, machine)
print os.uname() #('Linux', 'striky-desktop', '2.6.24-21-generic', '#1 SMP Tue Oct 21 23:43:45 UTC 2008', 'i686')
os.getcwd()
بتعيد المسار الحالى
print os.getcwd() /home/striky/workspace/pytut/src
os.getcwdu()
مثل سابقتها ولكن بتعمل ريترن ب unicode
os.environ
هى dictionary مخزن فيه متغير البيئة environment مثل ال HOME, LOGNAME, PATH,.. etc للإطلاع عليهم
for key, val in os.environ.items(): print key, " => ", val
للحصول على مفتاح بعينه
os.getenv(key, default)
للخصول على قيمة مفتاح ما فى الenviron
print os.getenv("HOME")
ال default سيتم اعادتها فى حالة عدم وجود المفتاح
انا root ?
def isroot(): return os.getenv("USER")=="root"
طبعا تقدر تستخدم ال keys, values methods الخاصة بال environ dictionary.
os.putenv(key, value)
إضافة key لل environment بقيمة value
os.unsetenv(key)
حذف key ما
os.chdir(to)
بتقوم بنقل المسار الحالى cwd الى to
print os.getcwd() os.chdir("/home/striky") print os.getcwd() os.chdir("Music") print os.getcwd() output /home/striky/workspace/pytut/src /home/striky /media/s3/Music
لاحظ ان Music هنا symbolic link تحت /home/striky وبيشير ل /media/s3/Music
os.listdir(path)
بتقوم بإعادة list من مكونات ال path
p=os.getcwd() #/home/striky/workspace/pytut/src print os.listdir(p) ['userstringtest.py', 'iosess.py', 'gcombo.py', 'iohelpers.py', 'oopsample.py', 'iotest.xcd', 'gtk1.py', 'complpath.py']
os.link(src,dest)
بتنشئ hard link من src الى dest
os.symlink(src, dest)
بتنشئ symbolic link من src إلى dest
os.unlink(path)
حذف path
os.remove(path)
مثل os.unlink
os.rmdir(path)
لحذف مجلد معين
os.rename(src, dest)
اعادة التسمية
os.removedirs(path)
بتقوم بالحذف من اسفل لأعلى مثلا
os.removedirs('foo/bar/baz')
ستقوم بحذف مجلد baz اولا ثم bar ثم foo
chmod(path, mode)
بتقوم بتعديل ال mode على path
chown(path, uid, gid)
تحديد ال uid, gid على path معين
print os.sep # /
الفاصل العناصر المسار
/home/striky
print os.curdir #.
المجلد الحالى وهى ال ".”
print os.altsep#None
حرف فاصل بديل
print os.pardir#..
المجلد الأب وهى ال "..”
print os.extsep#.
الفاصل للإمتدادات وهو ال ".”
print os.pathsep#:
الفاصل فى متغير ال PATH وهنا:
print repr(os.linesep)#\n
الفاصل بين السطور وهنا هو ال "\n”
p=os.getcwd() #/home/striky/workspace/pytut/src F=p+r'/'+"iohelpers.py" print op.basename(F) print op.isfile(F) print op.islink(F) print op.isabs(F) print op.isdir(F) print op.isdir(p) print op.ismount("/media/s3") print op.abspath(F) print op.dirname(F) print op.split(F) print op.splitdrive(F) print op.splitext(F) print op.exists(F+"xx")#Nope! print op.getatime(F) #last access time print op.getmtime(F) #last modification time print op.getsize(F) #file size. print op.join("/home", "striky", "Music")
الناتج
iohelpers.py True False True False True True /home/striky/workspace/pytut/src/iohelpers.py /home/striky/workspace/pytut/src ('/home/striky/workspace/pytut/src', 'iohelpers.py') ('', '/home/striky/workspace/pytut/src/iohelpers.py') False 1226557143.0 1226557142.0 521 /home/striky/Music ('/home/striky/workspace/pytut/src/iohelpers', '.py')
exists(path)
هل المسار موجود ؟
isfile(path)
هل ال path ملف؟
isdir(path)
هل ال path مجلد؟
islink(path)
هل ال path عبارة عن link ؟
ismount(path)
هل هو عبارة عن نقطة ضم ؟
isabs(path)
هل هو المسار بالكامل ؟
basename(path)
القاعدة فى المسار
abspath(path)
المسار المطلق
dirname(path)
اسم المجلد
getatime(path)
الحصول على توقيت ال last access
getmtime(path)
الحصول على توقيت ال last modification
getctime(path)
الحصول على توقيت ال last change او ال last creation اذا كان على windows
getsize(path)
الحصول على مساحة path
join(a)
لدمج مكونات الpath بإستخدام الفاصل المناسب
split(path)
تقوم بإعادة tuple مكونة من ال dirname وال basename
splitdrive(path)
تقوم بإعادة tuple مكونة من ال drive, وباقى المسار
splitext(path)
تقوم بإعادة tuple مكونة من المسار كامل بدون الإمتداد و الإمتداد
File Pointer
يمكن تكون مليت من إستخدام FileHandler.write
>>>F = open(fileName, 'w') >>>print >> F, 'Hola' #It will write the Hola word to the file that we opened >>>F.close() >>>F=open(fileName, 'r') >>>for line in F.readlines(): print line
Hola #Output!
على فرض إنك هتعمل File ودا معناه إنك هتستخدم ال w' permission'
>>> f = open('C:\\2.txt', 'w') #Open 2.txt for writing mode. >>> print >> f, 'Hola!' #Add 'Hola' to it >>> print >> f, 'Hello!' # same >>> print >> f, 'Using File Pointer !' #the same >>> f.close() #closing the file handler. >>> f = open('C:\\2.txt', 'r') # Open in reading mode. >>> for line in f.readlines(): #iterates through the file lines print line #printing each line.
#Here is the output. Hola! Hello! Using File Pointer !
>>>f.close() #closing the handler.
طب تمام .. هنفتح ال File مرة تانية ولكن فى ال Append mode
>>> f=open('C:\\2.txt', 'a') >>> print >> f, 'Programming Fr34ks r0x!' >>> print >> f, 'File pointers are', #Note : this comma is used to avoid printing a new line. >>> print >> f, ' so great' # added to the line 'File pointers are' >>> f.close()
نقرا اللى مكتوب فى ال File بإننا نعمل Iteration بسيطة على ال filehandler.readlines method
>>> f=open('C:\\2.txt', 'r') >>> for line in f.readlines(): print line
# The output Hola! Hello! Using File Pointer ! Programming Fr34ks r0x! File pointer are so great
التعامل مع ملفات CSV و INI
ConfigParser
موديل ConfigParser لمعالجة ملفات ال .ini “لاعلاقة لها بالرجيسترى!” ملف ال .ini نوع قديم من وصف البيانات ومستخدم بكثرة فى التطبيقات القديمة نسبيا مثال
[program] name = SVM version = 0.2.4 license = GPLv3 [author] name = Ahmed Youssef email = guru.python@gmail.com
هنا فى الملف يوجد 2 sections او قسمين الأول program والثانى author كل منهم بيحوى keys/values “فى بيسموها اوبشنز" براحتك مثلا ال name هو key تحت ال program section وقيمته SVM احفظ الملف السابق وليكن tst.cfg
1- استدعى ال ConfigParser موديل
from ConfigParser import *
2- انشئ اوبجكت
cp=SafeConfigParser() #create an object of SafeConfigParser
لاحظ ان فى كذا كلاس RawConfigParser, ConfigParser, SafeConfigParser فال RawConfigParser هو الأب واشتقه ال ConfigParser وهو الأب ل SafeConfigParser لذا قم بإستخدامه دائما
3- قم بقراءة الملف
cp.read("tst.cfg") #read by filename.
ال configparser object اللى انشئناه cp بيقوم بقراءة الملف بإستخدام ال read method
.add_section(section)
لإضافة سكشن جديد
.set(section, key, value)
لإضافة key جديد تحت القسم section وله قيمة value
.sections()
للحصول على جميع الأقسام
.has_section(section)
هل يوجد قسم بإسم section ؟
.get(section, key)
للحصول على قيمة ل key تحت section
.options(section)
للحصول على كل الoptions تحت section معين
.has_option(section, option)
هل section يحوى option بإسم option ؟
.items(section)
الحصول على list مكونة من tuples بتشمل key, value مثلا
[('name', 'Ahmed Youssef'), ('email', 'guru.python@gmail.com')]
.write(fp)
كتابة الملف سواء على ال stdout او فى ملف ما.. الخ الخ فى مجموعة من ال Errors مثلا NoSectionError, ParsingError, DuplicateSectionError, NoOptionError ودى فى حال محاول الوصول لقسم او اختيار غير موجود او محاولة التكرار او خطأ فى معالجة الملف "كتابة بصورة غير سليمة" وغيرهم..
من الحاجات اللى تهمك.. السكاشن والoptions
SECTCRE = re.compile( r'\[' # [ r'(?P<header>[^]]+)' # very permissive! r'\]' # ] )
OPTCRE = re.compile( r'(?P<option>[^:=\s][^:=]*)' # very permissive! r'\s*(?P<vi>[:=])\s*' # any number of space/tab, # followed by separator # (either : or =), followed # by any # space/tab r'(?P<value>.*)$' # everything up to eol )
تطبيق على الملف السابق
from ConfigParser import * import sys cp=SafeConfigParser() #create an object of SafeConfigParser cp.read("tst.cfg") #read by filename. print cp print "Sections: ", cp.sections() print "Options under [program]: ", cp.options("program") print cp.items("author") cp.add_section("links") cp.set("links", "pf", "http://www.programming-fr34ks.net") cp.set("links", "python", "http://www.python.org") cp.set("author", "website", "http://ahmedyoussef.wordpress.com") #print it out... for sec in cp.sections(): print "--%s:"%sec for key, value in cp.items(sec): print "\t", key, " = ", value print "--------" cp.write(sys.stdout)
الناتج
<ConfigParser.SafeConfigParser instance at 0xb7dc0f8c> Sections: ['program', 'author'] Options under [program]: ['version', 'name', 'license'] [('name', 'Ahmed Youssef'), ('email', 'guru.python@gmail.com')] --program: version = 0.2.4 name = SVM license = GPLv3 --links: python = http://www.python.org pf = http://www.programming-fr34ks.net --author: website = http://ahmedyoussef.wordpress.com name = Ahmed Youssef email = guru.python@gmail.com -------- [program] version = 0.2.4 name = SVM license = GPLv3 [links] python = http://www.python.org pf = http://www.programming-fr34ks.net [author] website = http://ahmedyoussef.wordpress.com name = Ahmed Youssef email = guru.python@gmail.com
راجع ConfigParser.py للإطلاع على المزيد
معالجة ملفات ال CSV
CSV هى اختصار ل comma separated values من الأسم واضح انها تستخدم فى تمثيل قيم مع فصلها بإستخدام الفاصلة (الcomma) فى صفوف (تستخدم عادة فى استيراد او تصدير بيانات ما ربما قاعدة بيانات مثلا؟) لاحظ ممكن يكون الفاصل مجرد مسافة او سلاش / او او او ولكن الأشهر هو ال فاصلة مثال
ahmed, 19, m ayman, 20, m
وقد تحتوى على صف اول يمثل الهيدر (يشمل عناوين الأعمدة)
name, age, sex ahmed, 19, m ayman, 20, m
على فرض لدينا ملف بإسم somefile.csv وفيه البيانات التالية
ahmed, m, 19 wael, m, 20 radwa, f, 19 gina, f, 21 ayman, m, 20
استدعى ال csv module كالتالى
import csv
قم بإنشاء reader object “مسئول عن القراءة للملف ومعالجته" بإستخدام cvs.reader()
reader=csv.reader(open("somefile.csv", "rb")) #default dialect. #b as a catch for win32
. تقدر تستخدم ال for loop مع ال reader فهى تقوم بعمل yield لكل صف يتم قراءته وللحصول على رقم الصف استخدم ال line_num
for row in reader: print row, " at: ", reader.line_num
فلنقم بتحسين المثال بعض الشئ
import csv f=open("somefile.csv", "rb") try: reader=csv.reader(f) #default dialect. #b as a catch for win32. for row in reader: print row, " at: ", reader.line_num except Exception, ex: print ex.message finally: f.close()
اذا اردت ربط الصف بقاموس وذلك بتحديد اسماء الأعمدة كالتالى
reader=csv.DictReader(f, fieldnames=("name", "age", "sex")) #default dialect. #b as a catch for win32. for row in reader: print row, " at: ", reader.line_num print row["name"] #the name column
للكتابة الموضوع سهل ايضا
بتنشئ writer (كاتب) من csv.writer
تكتب الheader (اسماء الاعمدة) بإستخدام الطريقة writer.writerow
وتعمل دوارة على المدخلات لكتابة كل صف
على سبيل المثال
import csv f=open("somefile1.csv", "w") try: writer=csv.writer(f) inputrows=( (1, "ahmed", "ahmedf1@gmail.com"), (2, "ayman", "aymanf2@gmail.com"), (3, "smsm", "smsm@yahoo.com") ) headers=("id", "user", "email") writer.writerow(headers) for row in inputrows: writer.writerow(row) except Exception, ex: print ex.message finally: f.close()
للمزيد حول ال CSV راجع وثائق بايثون
