בקטע הזה, נבחן כמה מהמודולים של כלי העזר הסטנדרטיים של Python שיעזרו לכם לפתור בעיות נפוצות.
מערכת קבצים – os, os.path, turnil
המודולים *os* ו-*os.path* כוללים פונקציות רבות לאינטראקציה עם מערכת הקבצים. המודול *shutil* יכול להעתיק קבצים.
- מסמכי מודול של מערכת הפעלה
- filenames = os.listdir(dir) -- רשימה של שמות קבצים בנתיב הספרייה הזה (לא כולל . ו ..). שמות הקבצים הם רק השמות בספרייה, ולא הנתיבים המוחלטים שלהם.
- os.path.join(dir, filename) – אם נותנים שם קובץ מהרשימה שלמעלה, אפשר להשתמש בו כדי לחבר את ה-dir ושם הקובץ יחד כדי ליצור נתיב
- os.path.ABpath(path) – נתיב, מוחזר צורה מוחלטת, למשל /home/nick/foo/bar.html
- os.path.dirname(path), os.path.basename(path) – ניתן dir/foo/bar.html, החזרת שם הדומיין "dir/foo" ו-basename "bar.html"
- os.path.exists(path) – אם קיים
- os.mkdir(dir_path) -- הופך את dir אחד, os.makedirs(dir_path) – יוצר את כל מה שצריך בנתיב הזה
- turnil.copy(source-path, dest-path) – העתקת קובץ (ספריות נתיב היעד צריכות להתקיים)
## Example pulls filenames from a dir, prints their relative and absolute paths def printdir(dir): filenames = os.listdir(dir) for filename in filenames: print(filename) ## foo.txt print(os.path.join(dir, filename)) ## dir/foo.txt (relative to current dir) print(os.path.abspath(os.path.join(dir, filename))) ## /home/nick/dir/foo.txt
התנסות במודול פועלת היטב עם הפונקציות המובנות של python help() ו-dir() . במפענח, מבצעים ייבוא של מערכת הפעלה ולאחר מכן משתמשים בפקודות האלה ובודקים מה זמין במודול: dir(os), help(os.listdir), dir(os.path), help(os.path.dirname).
הפעלת תהליכים חיצוניים – תהליך משנה
המודול *תהליך משנה* מאפשר להריץ פקודות חיצוניות בקלות ולתעד את הפלט שלהן.
- מסמכי מודולים של עיבוד משנה
- פלט = subprocess.check_output(cmd, stderr=subprocess.STDOUT) -- מפעיל את הפקודה, מחכה ליציאה, ומחזיר את טקסט הפלט. הפקודה תפעל עם הפלט הסטנדרטי והשגיאה הרגילה שלה, משולבים בטקסט פלט יחיד. אם הפעולה נכשלת, היא גורמת ל-CalledProcessError.
- אם אתם רוצים יותר שליטה בהרצה של תהליך המשנה, עיינו ב-subprocess.popen class.
- יש גם עיבוד פשוט (subprocess.call(cmd) שמריץ את הפקודה, ומכניס את הפלט שלה לפלט ומחזיר את קוד השגיאה שלה. הדבר מתאים אם ברצונך להריץ את הפקודה אך אין לך צורך לתעד את הפלט שלה במבני הנתונים של python.
import subprocess ## Given a dir path, run an external 'ls -l' on it -- ## shows how to call an external program def listdir(dir): cmd = 'ls -l ' + dir print("Command to run:", cmd) ## good to debug cmd before actually running it (status, output) = subprocess.getstatusoutput(cmd) if status: ## Error case, print the command's output to stderr and exit sys.stderr.write(output) sys.exit(status) print(output) ## Otherwise do something with the command's output
חריגים
חריגה היא שגיאה בזמן הריצה שעצרת את הביצוע הרגיל בשורה מסוימת ומעבירה את הבקרה לקוד טיפול בשגיאות. החלק הזה מציג את השימושים הבסיסיים ביותר של חריגים. לדוגמה, שגיאת זמן ריצה עשויה להיות מצב שבו משתנה שנעשה בו שימוש בתוכנית אינו מכיל ערך (ValueError .. בטח כבר ראית זאת מספר פעמים), או שגיאה בפעולה של פתיחת קובץ מפני שהקובץ אינו קיים (IOError). מידע נוסף זמין במדריך החריגים וברשימת החריגים המלאה.
ללא קוד לטיפול בשגיאות (כפי שעשינו עד עכשיו), חריג בזמן הריצה פשוט עוצר את התוכנית עם הודעת שגיאה. זוהי התנהגות ברירת מחדל טובה, ונתקלתם בה הרבה פעמים. אפשר להוסיף "ניסיון חריג" את המבנה של הקוד כדי לטפל בחריגים, כך:
try: ## Either of these two lines could throw an IOError, say ## if the file does not exist or the read() encounters a low level error. f = open(filename, 'rb') data = f.read() f.close() except IOError: ## Control jumps directly to here if any of the above lines throws IOError. sys.stderr.write('problem reading:' + filename) ## In any case, the code then continues with the line after the try/except
הקטע Try: כולל את הקוד שעלול לגרום לחריגה. הקטע 'חוץ': מכיל את הקוד שירוץ אם קיים חריג. אם אין יוצא מן הכלל, המערכת תדלג על הקטע 'למעט:' (כלומר, הקוד מיועד לטיפול בשגיאות בלבד ולא לתרחיש ה'רגיל' בקוד). אפשר לקבל מצביע לאובייקט החריג עצמו עם התחביר "except IOError as e: ." (e מצביע על האובייקט החריג).
HTTP – urllib ו-urlparse
המודול *urllib.request* מספק אחזור כתובות URL – כתובת URL נראית כמו קובץ שאפשר לקרוא ממנו. המודול *urlparse* יכול להפריד ולהרכיב כתובות URL.
- מסמכי המודול urllib.request
- ufile = urllib.request.urlopen(url) -- מחזירה קובץ כמו אובייקט עבור כתובת אתר זו
- text = ufile.read() -- יכול לקרוא ממנו, כמו קובץ ('readlines() ' וכן הלאה)
- info = ufile.info() – פרטי המטא של הבקשה. info.gettype() הוא סוג ה-mime, לדוגמה 'text/html'
- baseurl = ufile.geturl() -- מקבל את "base" כתובת האתר של הבקשה, שעשויה להיות שונה מהמקורית בגלל הפניות לכתובות אחרות
- urllib.request.urlretrieve(url, filename) – הורדת נתוני כתובת ה-URL לנתיב הקובץ הנתון
- urllib.parse.urljoin(baseurl, url) -- כאשר מזינים כתובת URL שעשויה להיות מלאה או לאה וכתובת הבסיס של הדף שממנו היא מגיעה מחזירה כתובת URL מלאה. צריך להשתמש ב-geturl() למעלה כדי לספק את כתובת ה-URL הבסיסית.
כל החריגים נמצאים בכתובת urllib.error.
from urllib.request import urlopen ## Given a url, try to retrieve it. If it's text/html, ## print its base url and its text. def wget(url): ufile = urlopen(url) ## get file-like object for url info = ufile.info() ## meta-info about the url content if info.get_content_type() == 'text/html': print('base url:' + ufile.geturl()) text = ufile.read() ## read all its text print(text)
הקוד שלמעלה פועל כמו שצריך, אבל לא כולל טיפול בשגיאות אם כתובת URL לא פועלת מסיבה כלשהי. זו גרסה של הפונקציה שמוסיפה לוגיקה לניסיון/חריג להדפסת הודעת שגיאה אם הפעולה של כתובת ה-URL נכשלה.
אם נראה ש-urlopen()
מושעה, ייתכן שהמערכת לא תאפשר גישה ישירה לחלק
כתובות http. כדי לאמת זאת, אפשר לנסות לאחזר את אותה כתובת URL באמצעות wget
, או
curl
. אם גם תוכנות אלה נכשלות, יהיה עליך לאחזר תוכן http באמצעות שרת proxy
לאחר השיפור. המדריך הזה לא עוסק בהגדרת גישה לשרת proxy.
## Version that uses try/except to print an error message if the ## urlopen() fails. def wget2(url): try: ufile = urlopen(url) if ufile.info().get_content_type() == 'text/html': print(ufile.read()) except IOError: print('problem reading url:', url)
פעילות גופנית
כדי לתרגל את החומר של מערכת הקבצים והפקודות החיצוניות, אפשר לעיין במאמר העתקת תרגיל מיוחד. כדי לתרגל את החומר של כתובת ה-URL, אפשר לעיין בתרגיל Log Puzzle.