עבודה עם קבצי קוד שונים
הפקולטה לפיזיקה, הטכניון. חורף 2013
מרצה: רונן אברבנאל
עד כה, עבדנו ישירות מול המפרש: הקלדנו פקודות והם בוצעו מיידית.
זה נחמד לפעולות קטנות ופעולות ביניים, אבל זה קצת מטופש לעבוד ככה כל היום .
מומלץ לעבוד עם עורך טקסט ש"מכיר" את פייתון: בפרט, כזה שצובע מילים שמורות בפייתון, כמו למשל כאן:
if 2==3:
pass
רצוי גם כזה שיודע לייצר 4 רווחים כשלוחצים על טאב, ויותר טוב: כזה שעושה טאב לבד כאשר מסיימים שורת קוד בנקודותיים.
בכל מקרה, יש להשתמש בתוכנה שיוצרת קובץ טקסט פשוט. פנקס רשימות (notepad) יעשה את העבודה, גם אם לא טוב במיוחד. Word אפילו לא ינסה.
אפשר להשתמש ב-scite שמגיע יחד עם ההתקנה של winPython, ב-notepad++ או באחד מעשרות עורכים טקסט אחרים.
סקריפט הוא קובץ המכיל רצף של פקודות בזו אחר זו, שמבוצעות על ידי המפרש. סקריפטי פייתון הם קובצי טקסט פשוטים, עם סיימות .py
%load ../example_code/example1.py
message = "Some string"
for word in message.split():
print word
Some string
message = "Hello how are you?"
for word in message.split():
print word
קובץ זה ניתן להריץ מתוך ipython באמצעות
%run ../example_code/example1.py
Hello how are you?
message
'Hello how are you?'
לאחר שהקובץ הורץ, אפשר לגשת למשתנים (הגלובאליים, אלו שלא נמצאים בשום פונקציה) מתוך הסביבה.
ניתן להריץ סקריפט כ"תוכנה עצמאית" ישירות באמצעות המפרש,
$ python example1.py
Hello
how
are
you?
רק חלק מה"פקודות" והפונקציות של פייתון זמינות מרגע שפחנו את המפרש (או, מרגע שהתחלנו לכתוב קוד). חלק מהפקודות והפונקציות נמצאות בתוך "מודולים" אותם יש לייבא במפורש.
import antigravity
אחד המודולים השימושיים והנפוצים בפייתון הוא המודל os המכיל פקודות שקשורות לקבצים, למחשב ולמערכת ההפעלה
import os
os
<module 'os' from '/usr/lib/python2.7/os.pyc'>
os.listdir("/lib64")
['ld-linux-x86-64.so.2']
למשל, הפונקציה listdir שמקבלת שם של ספריה ומחזירה רשימה של קבצים הנמצאים בספריה
אפשר לייבא גם פקודות בודדות מתוך מודול:
from os import listdir
listdir(".")
['.ipynb_checkpoints', 'lecture1.ipynb', 'lecture2.ipynb', 'lecture4.ipynb', 'Untitled0.ipynb', 'lecture3.ipynb']
וכן לשנות את השם של מודולים מיובאים לשם קיצור, למשל,
import numpy as np
my_new_zeros = np.zeros
my_new_zeros(5)
array([ 0., 0., 0., 0., 0.])
הערה אפשר ליבא את כל הפונקציות מתוך מודול מסויים באמצעות *, למשל,
from os import *
זה נוח, אבל עלול גם ליצור בעיות, בפרט, אם יובאו שני מודולים ובהם פונקציות עם אותו השם. לכן, יש להמנע מזה.
כתיבת וקריאת קבצי טקסט "פשוטים" בפייתון היא עסק פשוט למדי, אבל נדון בו רש בשטחיות. בהמשך, נראה איך עובדים עם קבצים "מסובכים" יותר.
f = open("somefile.txt","w")
f
<open file 'somefile.txt', mode 'w' at 0x2e774b0>
כאן, הפרמטר הראשון הוא שם הקובץ, והפרמטר השני הוא אחד (או יותר) מהתווים r,w,a, על מנת לפתוח את הקובץ לקריאה בלבד, לכתיבה או להוספת טקסט בסופו.
f.write("This is content of a file\n with two lines")
f.close()
חשוב מאוד לסגור קובץ בגמר השימוש!
כדי לקרוא מקובץ,
f = open("somefile.txt","r")
content = f.read()
print content
f.close()
This is content of a file with two lines
בדוגמאות השונות ראינו מדי פעם שהמפרש זרק עלינו שגיאה. כשכותבים קוד ישירות זה נחמד - יודעים שהיתה בעיה ופועלים בהתאם, אבל אם כותבים סקריפטים ארוכים, שגיאה כזו גורמת להפסקת הריצה.
1/0
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-8-05c9758a9c21> in <module>() ----> 1 1/0 ZeroDivisionError: integer division or modulo by zero
d = {1:1, 2:2}
d[3]
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-9-38f25624df81> in <module>() 1 d = {1:1, 2:2} ----> 2 d[3] KeyError: 3
l = [1,2,3]
l[3]
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-10-0e767cd8fb1f> in <module>() 1 l = [1,2,3] ----> 2 l[3] IndexError: list index out of range
open("there_is_no_file","r")
--------------------------------------------------------------------------- IOError Traceback (most recent call last) <ipython-input-11-b30199f33520> in <module>() ----> 1 open("there_is_no_file","r") IOError: [Errno 2] No such file or directory: 'there_is_no_file'
כדי לתפוס שגיאות, אפשר להשתמש ב-try, except
try:
open("somefile.txt","r")
except:
print "some error happend!"
אפשר לתפוס שגיאה ולא לעשות כלום באמצעות pass
try:
a = 1/0
except:
pass #Do nothing
הערה פייתון לא אוהב בלוקים ריקים. אם איפשהו אתם כותבים בלוק ואין לכם מה לכתוב בו, שימו בו pass.
אפשר גם לתפוס שגיאות מסוגים ספציפיים:
try:
l = [1,2,3]
l[4]
except KeyError:
print "Key Error catched"
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-17-3bf3e93f1555> in <module>() 1 try: 2 l = [1,2,3] ----> 3 l[4] 4 except KeyError: 5 print "Key Error catched" IndexError: list index out of range
כאן, הקוד זרק IndexError אבל ניסינו לתפוס רק KeyError, אז הוא לא נתפס. לו היינו כותבים,
try:
l = [1,2,3]
l[4]
except IndexError:
print "Index Error catched"
Index Error catched
אבל למה לתפוס רק סוגים מסויימים של שגיאות?
לפעמים סוגים מסויימים של שגיאות הם "חוקיים" - אם הקובץ לא נמצא אפשר לעבור הלאה, אבל בטעות חילקנו באפס, זו קטסטרופה, ואנחנו רוצים להודיע למשתמש.
לא חייבים לתפוס שגיאות מיד. אפשר גם לתת להן לצוף "למעלה"
def open_end_divide(filename, number):
f = open(filename,"r")
print "file opened"
f.close()
return 1./number
open_end_divide("somefile.txt", 3)
file opened
0.3333333333333333
try:
open_end_divide("nofile.tמxt", 3)
except DefaultError, m:
print m
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-20-5fe6e823b53c> in <module>() 2 open_end_divide("nofile.tמxt", 3) 3 ----> 4 except Error, m: 5 print m NameError: name 'Error' is not defined
try:
open_end_divide("somefile.txt", 0)
except Exception, m:
print m.args, m.message
("name 'open_end_divide' is not defined",) name 'open_end_divide' is not defined
השתמשו ברשימה argv שנמצאת במודול sys * הפרמטר הראשון הוא שם ספריה והפרמטר השני הוא מילה לחיפוש. * התוכנית מדפיסה את שמות כל קבצי ה-.py בספריה המופיעה בפרמטר הראשון, המכילים את המילה בפרמטר השני.
נסו לפתוח ספריה לא קיימת וקבלו הודעת שגיאה. שנו את התוכנית כך שאם הספריה לא קיימת, התוכנית לא תבצע דבר, ורק תדפיס הודעת שגיאה.