Tiện ích Python

Trong phần này, chúng ta sẽ xem xét một số mô-đun tiện ích tiêu chuẩn của Python để giải quyết các vấn đề thường gặp.

Hệ thống tệp -- os, os.path, offil

Các mô-đun *os* và *os.path* bao gồm nhiều chức năng để tương tác với hệ thống tệp. Mô-đun *shutil* có thể sao chép tệp.

  • tài liệu về mô-đun hệ điều hành
  • tên tệp = os.listdir(dir) – danh sách tên tệp trong đường dẫn thư mục đó (không bao gồm . và ..). Tên tệp chỉ là tên trong thư mục, không phải là đường dẫn tuyệt đối của tệp.
  • os.path.join(dir, tên tệp) – được cung cấp tên tệp trong danh sách trên, hãy sử dụng tên tệp này để đặt thư mục và tên tệp cùng nhau tạo thành đường dẫn
  • os.path.abspath(path) – được cung cấp một đường dẫn, sẽ trả về dạng tuyệt đối, ví dụ: /home/nick/foo/bar.html
  • os.path.dirname(path), os.path.basename(path) – đưa ra dir/foo/bar.html, trả về tên thư mục "dir/foo" và tên cơ sở "bar.html"
  • os.path.exists(path) – đúng nếu có
  • os.mkdir(dir_path) – tạo một thư mục, os.makedirs(dir_path) tạo tất cả các tệp di chuyển cần thiết trong đường dẫn này
  • offil.copy(source-path, dest-path) – sao chép tệp (thư mục đường dẫn đích phải tồn tại)
## 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

Khám phá một mô-đun hoạt động tốt với các hàm python help() và dir() tích hợp sẵn. Trong trình thông dịch, hãy nhập một "import os", sau đó dùng các lệnh sau để xem các tính năng có trong mô-đun: dir(os), help(os.listdir), dir(os.path), help(os.path.dirname).

Chạy quy trình bên ngoài – quy trình phụ

Mô-đun *quy trình phụ* là một cách đơn giản để chạy lệnh bên ngoài và chụp kết quả của lệnh đó.

  • tài liệu về mô-đun quy trình phụ
  • output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) – chạy lệnh, đợi lệnh thoát rồi trả về văn bản đầu ra. Lệnh này được chạy với dữ liệu đầu ra chuẩn và lỗi chuẩn kết hợp thành một văn bản đầu ra. Nếu không thành công, lỗi sẽ gửi một invokeProcessError.
  • Nếu bạn muốn kiểm soát nhiều hơn việc chạy quy trình phụ, hãy xem lớp subprocess.popen
  • Ngoài ra, còn có một subprocess.call(cmd) đơn giản chạy lệnh và kết xuất đầu ra của lệnh đó vào đầu ra của bạn rồi trả về mã lỗi. Cách này phù hợp nếu bạn muốn chạy lệnh nhưng không cần ghi kết quả của lệnh vào cấu trúc dữ liệu python của mình.
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

Trường hợp ngoại lệ

Một ngoại lệ biểu thị lỗi thời gian chạy làm tạm dừng quá trình thực thi thông thường tại một dòng cụ thể và chuyển quyền kiểm soát sang mã xử lý lỗi. Phần này chỉ giới thiệu các cách sử dụng ngoại lệ cơ bản nhất. Ví dụ: lỗi thời gian chạy có thể xảy ra khi biến được dùng trong chương trình không có giá trị (ValueError .. bạn có thể đã thấy lỗi này một vài lần) hoặc lỗi thao tác mở tệp do tệp không tồn tại (IOError). Tìm hiểu thêm trong hướng dẫn về ngoại lệ và xem toàn bộ danh sách ngoại lệ.

Nếu không có bất kỳ mã xử lý lỗi nào (như chúng ta đã thực hiện từ trước đến nay), thì ngoại lệ thời gian chạy sẽ chỉ tạm dừng chương trình kèm theo thông báo lỗi. Đây là hành vi mặc định tốt mà bạn đã thấy nhiều lần. Bạn có thể thêm cấu trúc "thử/ngoại trừ" vào mã để xử lý các ngoại lệ như sau:

  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

Phần try: chứa mã có thể trả về một ngoại lệ. Phần ngoại trừ: giữ mã để chạy nếu có ngoại lệ. Nếu không có ngoại lệ, phần "Exception" (trừ:) sẽ được bỏ qua (nghĩa là mã đó chỉ dùng để xử lý lỗi, chứ không phải trường hợp "bình thường" của mã). Bạn có thể chuyển một con trỏ đến chính đối tượng ngoại lệ bằng cú pháp "ngoại trừ IOError dưới dạng e: .." (e trỏ đến đối tượng ngoại lệ).

HTTP – urllib và urlparse

Mô-đun *urllib.request* cung cấp tính năng tìm nạp url – làm cho url trông giống như một tệp bạn có thể đọc từ đó. Mô-đun *urlparse* có thể tách rời và đặt các URL với nhau.

  • tài liệu mô-đun urllib.request
  • ufile = urllib.request.urlopen(url) – trả về một tệp như đối tượng cho url đó
  • text = ufile.read() -- có thể đọc từ đó, như một tệp (readlines(), v.v. cũng hoạt động)
  • info = ufile.info() – thông tin meta cho yêu cầu đó. info.gettype() là loại mime, ví dụ: 'text/html'
  • baseurl = ufile.geturl() – nhận url "base" cho yêu cầu, có thể khác với bản gốc do có các lệnh chuyển hướng
  • urllib.request.url number(url, tên tệp) – tải dữ liệu url xuống theo đường dẫn tệp đã cho
  • urllib.parse.urljoin(baseurl, url) – khi được cung cấp một URL có thể đầy hoặc không đầy đủ và url cơ sở của trang bắt nguồn, sẽ trả về một url đầy đủ. Sử dụng geturl() ở trên để cung cấp URL cơ sở.

Tất cả các trường hợp ngoại lệ đều nằm trong 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)

Mã ở trên hoạt động tốt, nhưng không bao gồm xử lý lỗi nếu url không hoạt động vì lý do nào đó. Dưới đây là phiên bản của hàm này thêm logic thử/ngoại trừ để in thông báo lỗi nếu thao tác url không thành công.

Nếu urlopen() có vẻ đang bị treo, thì hệ thống của bạn có thể không cho phép truy cập trực tiếp vào một số địa chỉ http. Bạn có thể xác minh điều này bằng cách cố gắng tìm nạp cùng một url thông qua wget hoặc curl. Nếu các chương trình này cũng không thành công, bạn sẽ cần tìm nạp nội dung http thông qua dịch vụ proxy. Hướng dẫn này không đề cập đến cách định cấu hình quyền truy cập 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)

Bài tập

Để thực hành về hệ thống tệp và tài liệu các lệnh ngoài, hãy xem Sao chép bài tập đặc biệt. Để thực hành tài liệu urllib, hãy xem Log Puzzle Exercise (Bài tập câu đố nhật ký).