Nameerror name raw_input is not defined bị lỗi

Đến bây giờ chũng ta cũng chỉ mới nhắc đến các thông điệp lỗi, nhưng nếu bạn đã thử qua các ví dụ thì bạn có thể đã gặp nhiều hơn. Có (ít nhất) hai loại lỗi khác biệt: lỗi cú pháp và biệt lệ.

Show

    8.1 Lỗi cú pháp

    Lỗi cú pháp, còn biết đến như lỗi phân tích (parsing error), có lẽ là phàn nàn lớn nhất bạn gặp phải khi vẫn đang học Python:

    > while True print 'Hello world' File "", line 1, in ?
    while True print 'Hello world'
                   ^
    
    SyntaxError: invalid syntax

    Bộ phân tích lặp lại dòng gây lỗi và hiển thị một mũi tên nhỏ trỏ vào điểm đầu tiên lỗi được phát hiện. Lỗi nằm ở dấu hiệu phía trước mũi tên: trong ví dụ trên, lỗi được phát hiện ở từ khóa print, vì thiếu một dấu hai chấm (":") ở trước đó. Tên tập tin vào số dòng được hiển thị để bạn biết tìm lỗi ở chỗ nào nếu đầu vào là từ một kịch bản.

    8.2 Biệt lệ

    Cho dù một câu lệnh hoặc biểu thức là đúng đắn, nó vẫn có thể tạo lỗi khi thực thi. Những lỗi bị phát hiện trong lúc thực thi được gọi là biệt lệ và không tai hại một cách vô điều kiện: bạn sẽ học cách xử lý chúng trong các chương trình Python. Hầu hết các biệt lệ đều được xử lý bởi chương trình và dẫn đến kết quả là các thông điệp lỗi như ở đây:

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    Dòng cuối cùng của thông điệp lỗi cho biết chuyện gì xảy ra. Biệt lệ có nhiều kiểu, và kiểu được hiển thị như là một phần của thông điệp: các kiểu trong ví dụ là ZeroDivisionError, NameError và TypeError. Chuỗi được hiển thị như là kiểu biệt lệ là tên của biệt lệ có sẵn vừa xảy ra. Điều này đúng với tất cả các biệt lệ có sẵn, nhưng không nhất thiết đúng với các biệt lệ do người dùng định nghĩa (mặc dù đó là một quy ước hữu dụng). Các tên biệt lệ chuẩn là những từ định danh có sẵn (không phải là từ khóa).

    Phần còn lại cho biết chi tiết về kiểu biệt lệ và chuyện gì gây ra nó.

    Phần trước của thông điệp lỗi cho biết hoàn cảnh khi xảy ra biệt lệ, ở dạng lần ngược ngăn xếp (stack traceback). Bình thường nó chứa một lần ngược ngăn xếp liệt kê các dòng nguồn; tuy nhiên, nó sẽ không hiển thị các dòng đọc từ đầu vào chuẩn.

    Tham khảo thư viện Python liệt kê các biệt lệ có sẵn và ý nghĩa của chúng.

    8.3 Xử lý biệt lệ

    Chúng ta có thể viết những chương trình xử lý những biệt lệ được chọn. Hãy xem ví dụ sau, nó yêu cầu người dùng nhập vào dữ liệu cho tới khi một số nguyên được nhập, nhưng cũng cho phép người dùng ngưng chương trình (dùng Control-C hoặc phím tắt khác mà hệ điều hành hỗ trợ); lưu ý rằng sự ngắt quãng do người dùng tạo nên được đánh dấu bởi việc nâng biệt lệ KeyboardInterrupt .

    > while True: ... try: ... x = int(raw_input("Please enter a number: ")) ... break ... except ValueError: ... print "Oops! That was no valid number. Try again..." ...

    try (câu lệnh) hoạt động như sau.

    • Trước tiên, vế try (các câu lệnh giữa từ khóa try và except ) được thực thi.
    • Nếu không có biệt lệ nào xảy ra, vế except được bỏ qua và câu lệnh try kết thúc.
    • Nếu trong khi thực thi vế try xảy ra biệt lệ, phần còn lại của vế được bỏ qua. Sau đó nếu kiểu biệt lệ hợp với kiểu được chỉ định sau từ khóa except , thì vế except được thực thi, và rồi việc thực thi tiếp tục sau câu lệnh try .
    • Nếu biệt lệ xảy ra không hợp với biệt lệ được chỉ định ở vế except, nó sẽ được truyền ra các câu lệnh try bên ngoài; nếu không có đoạn mã xử lý nào, nó là một biệt lệ không được xử lý và việc thực thi dừng lại với một thông báo như trên.

    A try (câu lệnh) có thể có nhiều hơn một vế except, để chỉ rõ cách xử lý cho những biệt lệ khác nhau. Nhiều nhất là một đoạn xử lý (handler) sẽ được thực thi. Các đoạn xử lý chỉ xử lý biệt lệ xảy ra trong vế try tương ứng, không xử lý các biệt lệ trong các đoạn xử lý khác của cùng câu lệnh try . Vế except có thể định danh nhiều biệt lệ trong một bộ (tuple), ví dụ:

    ... except (RuntimeError, TypeError, NameError): ... pass

    Vế except cuối cùng có thể bỏ qua tên biệt lệ, có tác dụng như là một thay thế (wildcard). Phải hết sức cẩn trọng khi dùng nó, vì nó có thể dễ dàng che đi lỗi lập trình thật! Nó cũng có thể được dùng để in thông báo lỗi và sau đó nâng biệt lệ lại (re-raise exception) (nhằm cho phép nơi gọi xử lý biệt lệ):

    import sys try:

    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
    
    except IOError, (errno, strerror):
    print "I/O error(%s): %s" % (errno, strerror)
    
    except ValueError:
    print "Could not convert data to an integer."
    
    except:
    print "Unexpected error:", sys.exc_info()[0]
    raise
    
    try ... except (câu lệnh) có một vế elsekhông bắt buộc, mà khi có mặt sẽ phải đi sau tất cả các vế except. Nó dùng cho mã sẽ được thực thi nếu vế try không nâng biệt lệ nào. Ví dụ:

    for arg in sys.argv[1:]:

    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()
    
    Việc dùng vế else tốt hơn là thêm mã vào vế try vì nó tránh việc vô tình bắt một biệt lệ không được nâng từ mã được bảo vệ trong câu lệnh try ... except .

    Khi một biệt lệ xảy ra, nó có thể có một giá trị gắn liền, còn được biết đến như là thông sốcủa biệt lệ. Sự có mặt và kiểu của thông số phụ thuộc vào kiểu biệt lệ.

    Vế except có thể chỉ định một biến sau một (hoặc một bộ) tên biệt lệ. Biến đó được gán với một trường hợp biệt lệ (exception instance) với các thông số chứa trong

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    6. Để thuận tiện, trường hợp biệt lệ định nghĩa __getitem__ và __str__ để cho các thông số có thể được truy xuất và in ra trực tiếp mà không phải tham chiếu

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    7.

    Nhưng việc dùng

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    7 đã không được khuyến khích. Thay vào đó, cách dùng tốt nhất là truyền một thông số đơn lẻ vào một biệt lệ (có thể là một bộ nếu có nhiều thông số) và gán nó vào thuộc tính

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    9 . Ta cũng có thể tạo một biệt lệ trước và thêm các thuộc tính vào nó trước khi nâng.

    > try: ... raise Exception('spam', 'eggs') ... except Exception, inst: ... print type(inst) # the exception instance ... print inst.args # arguments stored in .args ... print inst # str allows args to printed directly ... x, y = inst # getitem allows args to be unpacked directly ... print 'x =', x ... print 'y =', y ... ('spam', 'eggs') ('spam', 'eggs') x = spam y = eggs

    Nếu biệt lệ có một thông số, nó sẽ được in ra như là phần cuối (`chi tiết') của thông điệp của những biệt lệ không được xử lý.

    Các phần xử lý biệt lệ không chỉ xử lý các biệt lệ xảy ra ngay trong vế try, mà còn xử lý cả biệt trong những hàm được gọi (trực tiếp hoặc gián tiếp) trong vế try. Ví dụ:

    > def this_fails(): ... x = 1/0 ...
    try: ... this_fails() ... except ZeroDivisionError, detail: ... print 'Handling run-time error:', detail ... Handling run-time error: integer division or modulo by zero

    8.4 Nâng biệt lệ

    raise (câu lệnh) cho phép nhà lập trình ép xảy ra một biệt lệ được chỉ định. Ví dụ:

    > raise NameError, 'HiThere' Traceback (most recent call last): File "", line 1, in ? NameError: HiThere

    Thông số đầu tiên cho raise chỉ định biệt lệ sẽ được nâng. Thông số (tùy chọn) thứ hai chỉ định thông số của biệt lệ. Hoặc là, các dòng trên có thể được viết

    > while True: ... try: ... x = int(raw_input("Please enter a number: ")) ... break ... except ValueError: ... print "Oops! That was no valid number. Try again..." ...

    0. Cả hai dạng đều đúng, nhưng người ta có vẻ chuộng dạng thứ hai hơn.

    Nếu bạn cần xác định xem một biệt lệ có được nâng chưa nhưng không định xử lý nó, dạng đơn giản hơn của câu lệnh raise cho phép bạn nâng lại (re-raise) biệt lệ:

    > try: ... raise NameError, 'HiThere' ... except NameError: ... print 'An exception flew by!' ... raise ... An exception flew by! Traceback (most recent call last): File "", line 2, in ? NameError: HiThere

    8.5 Biệt lệ tự định nghĩa

    Các chương trình có thể đặt tên biệt lệ riêng bằng cách tạo một lớp biệt lệ mới. Các biệt lệ thường nên kế thừa từ lớp Exception , trực tiếp hoặc gián tiếp. Ví dụ:

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    0

    Trong ví dụ này, mặc định __init__ của Exception đã được định nghĩa lại. Cách thức mới chỉ đơn giản tạo thuộc tính value . Nó thay thế cách thức mặc định tạo thuộc tính args .

    Các lớp biệt lệ có thể được định nghĩa để làm bất kỳ việc gì như các lớp khác, nhưng chúng thường là đơn giản và chỉ cung cấp một số thuộc tính để chứa thông tin về lỗi cho các phần xử lý biệt lệ. Khi tạo một mô-đun mà có thể nâng vài lỗi khác biệt, cách thông thường là tạo một lớp cơ sở cho các biệt lệ được định nghĩa bởi mô-đun đó, và kế thừa từ đó để tạo những lớp biệt lệ cụ thể cho những trường hợp lỗi khác nhau:

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    1

    Đa số biệt lệ được định nghĩa với tên tận cùng bằng ``Error'', tương tự như cách đặt tên của các biệt lệ chuẩn.

    Nhiều mô-đun chuẩn định nghĩa biệt lệ riêng cho chúng để thông báo những lỗi mà có thể xảy ra trong các hàm chúng định nghĩa. Thông tin thêm về các lớp được trình bày trong chương , ``Lớp''.

    8.6 Định nghĩa cách xử lý

    try (câu lệnh) có một vế không bắt buộc khác với mục đích định nghĩa những tác vụ dọn dẹp (clean-up action) mà sẽ được thực hiện trong mọi trường hợp. Ví dụ:

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    2

    A vế finally luôn được thực thi trước khi rời khỏi câu lệnh try , cho dù có xảy ra biệt lệ hay không. Khi một biệt lệ đã xảy ra trong vế try và không được xử lý bởi vế except (hoặc nó đã xảy ra trong một vế except hay else ), nó sẽ được nâng lại sau khi vế finally đã được thực thi. Vế finally cũng được thực thi ``trên đường ra'' khi bất kỳ vế nào của câu lệnh try được bỏ lại thông qua câu lệnh break, continue hay return . Một ví dụ phức tạp hơn:

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    3

    Như bạn có thể thấy, vế finally được thực thi trong mọi trường hợp. TypeError được nâng vì chia hai chuỗi không được xử lý bởi vế except và vì thế nên được nâng lại sau khi vế finally đã được thực thi.

    Trong các ứng dụng thực thế, vế finally được dùng để trả lại những tài nguyên ngoài (như tập tin, hoặc kết nối mạng), cho dù việc sử dụng tài nguyên có thành công hay không.

    8.7 Định nghĩa xử lý có sẵn

    Một số đối tượng định nghĩa các tác vụ dọn dẹp chuẩn để thực thi khi một đối tượng không còn được cần đến, cho dù việc xử dụng đối tượng là thành công hay thất bại. Xem qua ví dụ sau, nó thử mở một tập tin và viết nội dung của nó ra màn hình.

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    4

    Vấn đề với đoạn mã trên là nó để tập tin ngỏ trong một thời gian không xác định sau khi đoạn mã đã kết thúc. Đây không phải là vấn đề gì trong các đoạn kịch bản đơn giản, nhưng có thể là một vấn đề phức tạp đối với các ứng dụng lớn hơn. Câu lệnh with cho phép các đối tượng như tập tin được dùng theo một cách đảm bảo chúng sẽ được dọn dẹp đúng lúc và đúng đắn.

    > 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
    4 + spam*3 Traceback (most recent call last): File "", line 1, in ? NameError: name 'spam' is not defined
    '2' + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects

    5

    Sau khi câu lệnh được thực thi, tập tin f luôn được đóng lại, cho dù gặp phải vấn đề trong khi xử lý các dòng. Các đối tượng khác mà cung cấp những tác vụ dọn dẹp định nghĩa sẵn sẽ cho biết về điểm này trong tài liệu của chúng.