Cách in hàng đợi trong Python

- [Giảng viên] Bây giờ chúng ta đã hoàn thành việc triển khai hàng đợi trong Python, hãy áp dụng kỹ năng mới này vào thực tế với thử thách hàng đợi. Lời nhắc là tạo ba lớp cùng nhau mô hình hóa cách máy in có thể thực hiện lệnh in ra khỏi hàng đợi in. Có một số yêu cầu. Đầu tiên là một lớp có tên PrintQueue tuân theo việc triển khai cấu trúc dữ liệu hàng đợi. Yêu cầu thứ hai sẽ là một lớp có tên Công việc, có thuộc tính pages và mỗi công việc có thể có từ một đến 10 trang. Bạn có thể gán số này ngẫu nhiên trong chương trình của mình. Lớp công việc cũng nên có một phương thức trang in giảm số trang và một phương thức kiểm tra hoàn thành, phương thức này sẽ kiểm tra xem tất cả các trang đã được in hay chưa. Yêu cầu thứ ba là lớp máy in. Lớp máy in phải có một phương thức get job sử dụng phương thức de-queue tích hợp sẵn của queues để lấy công việc đầu tiên trong hàng đợi in ra khỏi hàng đợi. Đảm bảo rằng bạn tính đến trường hợp printqueue. các mục trống, nếu không bạn sẽ…

Thực hành trong khi bạn học với các tập tin bài tập

Tải xuống các tệp mà người hướng dẫn sử dụng để dạy khóa học. Theo dõi và học hỏi bằng cách xem, nghe và thực hành

Tải xuống các khóa học và học mọi lúc, mọi nơi

Xem các khóa học trên thiết bị di động của bạn mà không cần kết nối internet. Tải xuống các khóa học bằng ứng dụng LinkedIn Learning trên iOS hoặc Android của bạn

Hôm nọ, tôi đang cố gắng tìm cách theo dõi hàng đợi in trên Windows. Nhiệm vụ trước mắt là theo dõi những tài liệu nào đã được chuyển đến máy in và hoàn toàn thành công. Ý tưởng là khi quá trình in hoàn tất, tài liệu sẽ được lưu trữ. Để làm điều này, bạn cần PyWin32 [AKA. Phần mở rộng Python cho Windows]. Trong bài viết này, chúng ta sẽ xem xét một tập lệnh đơn giản để kiểm tra hàng đợi in

Đây là mã

import time
import win32print

#----------------------------------------------------------------------
def print_job_checker[]:
    """
    Prints out all jobs in the print queue every 5 seconds
    """
    jobs = [1]
    while jobs:
        jobs = []
        for p in win32print.EnumPrinters[win32print.PRINTER_ENUM_LOCAL,
                                         None, 1]:
            flags, desc, name, comment = p
            
            phandle = win32print.OpenPrinter[name]
            print_jobs = win32print.EnumJobs[phandle, 0, -1, 1]
            if print_jobs:
                jobs.extend[list[print_jobs]]
            for job in print_jobs:
                print "printer name => " + name
                document = job["pDocument"]
                print "Document name => " + document
            win32print.ClosePrinter[phandle]
            
        time.sleep[5]
    print "No more jobs!"
        
#----------------------------------------------------------------------
if __name__ == "__main__":
    print_job_checker[]

Trước hết, chúng tôi nhập win32print và mô-đun thời gian. Chúng tôi cần win32print để truy cập máy in. Chúng tôi tạo một vòng lặp có khả năng vô hạn để tiếp tục kiểm tra các lệnh in trong hàng đợi in. Nếu danh sách công việc luôn trống, điều đó có nghĩa là không còn gì trong hàng đợi in và chức năng sẽ thoát. Trong đoạn mã trên, chúng tôi sử dụng win32print. EnumPrinters[] để lặp qua các máy in được cài đặt trên máy. Đối số đầu tiên là một lá cờ [win32print. PRINTER_ENUM_LOCAL], thứ hai là tên [hoặc Không có trong trường hợp này] và thứ ba là mức thông tin. Có một số cờ chúng ta có thể sử dụng, chẳng hạn như PRINTER_ENUM_SHARED, PRINTER_ENUM_LOCAL hoặc PRINTER_ENUM_CONNECTIONS. Tôi đã sử dụng PRINTER_ENUM_LOCAL vì nó trả về tên máy in ở định dạng mà tôi có thể sử dụng với phương thức OpenPrinter của win32print. Chúng tôi làm điều này để truy vấn máy in để biết thông tin qua tay cầm. Để có danh sách các lệnh in, chúng tôi gọi win32print. EnumJobs[] với tay cầm in. Sau đó, chúng tôi lặp lại chúng và in ra tên máy in và tên tài liệu. Bạn không cần phải thực hiện tất cả các bản in này, nhưng tôi thấy nó hữu ích khi tôi viết mã. Đối với mục đích thử nghiệm, tôi khuyên bạn nên mở hàng đợi in và đặt thành "tạm dừng" để bạn có thể ngăn giấy in cho đến khi bạn sẵn sàng. Điều này cho phép bạn vẫn thêm các mục vào hàng đợi in mà bạn có thể truy vấn

Tôi đặt khoảng thời gian trễ 5 giây giữa các lần kiểm tra để đảm bảo không có bản cập nhật mới nào cho hàng đợi. Nếu có lệnh in, nó sẽ kiểm tra lại hàng đợi. Nếu không thì nó thoát ra khỏi vòng lặp

Hàng đợi là một kiểu dữ liệu trừu tượng tuyến tính với một số điểm khác biệt chính giữa các ngăn xếp. Hàng đợi chứa một bộ sưu tập các mục theo thứ tự mà chúng được thêm vào. Các mục được thêm vào phía sau hàng đợi và bị xóa khỏi phía trước hàng đợi. Bạn chạy vào hàng đợi mọi lúc. Lần cuối cùng bạn đi mua hàng tạp hóa, bạn có thể phải xếp hàng chờ thanh toán. Nếu bạn coi hàng đợi là một hàng khách hàng, một khách hàng tự thêm mình vào cuối hàng và cuối cùng rời khỏi hàng đầu. Điều này được gọi là nhập trước xuất trước hoặc FIFO. Điều này khác với các ngăn xếp theo kiểu nhập trước xuất trước. Ngoài ra, hàng đợi cũng duy trì trật tự nên khi bạn nghĩ về những người tham gia xếp hàng, thứ tự cũng được duy trì ở đó. Bây giờ hãy xem các ví dụ về hàng đợi trong Python

Một lớp xếp hàng

Đối với ví dụ này về hàng đợi trong Python, chúng tôi sẽ sử dụng một lớp sẽ có tất cả các phương thức cần thiết để triển khai các chức năng của hàng đợi. Lớp sẽ được đặt tên đơn giản là Hàng đợi và chúng tôi sẽ biểu thị hàng đợi của mình dưới dạng một danh sách. Trong phương thức __init__, chúng ta có thể khởi tạo các mục thành một danh sách trống. Để thiết lập chức năng cơ bản cần thiết để đưa mọi thứ vào và ra khỏi hàng đợi, chúng ta có thể tạo ra một enqueue[] để thêm và một dequeue[] để xóa. Phương thức enqueue[] cần một tham số của mục để chúng ta có thể thêm nó vào hàng đợi. Phương thức dequeue[] không cần tham số mục vì chúng tôi sẽ luôn xuất hiện ở cuối danh sách, phương thức này sẽ tự động lấy mục cuối cùng của danh sách cho chúng tôi. Để kiểm tra xem mục tiếp theo trong hàng đợi sẽ bị xóa, chúng ta có thể sử dụng phương thức peek[]. Chúng tôi cũng muốn có thể kiểm tra kích thước của hàng đợi bằng cách sử dụng size[] và liệu hàng đợi có trống hay không bằng cách sử dụng is_empty[]

class Queue:
    def __init__[self]:
        self.items = []

    def enqueue[self, item]:
        pass

    def dequeue[self]:
        pass

    def size[self]:
        pass

    def peek[self]:
        pass

    def is_empty[self]:
        pass

hàng đợi[]

Bây giờ chúng ta có thể bắt đầu mã hóa các phương thức chúng ta cần cho lớp Queue của mình. Chúng ta sẽ bắt đầu với phương thức enqueue[]. Đối với phương thức này, chúng ta phải truyền vào dưới dạng tham số mục mà chúng ta muốn thêm vào hàng đợi. Bên trong phần thân của phương thức của chúng tôi, chúng tôi muốn chèn mục này vào danh sách theo kiểu giống như hàng đợi. Với hàng đợi, chúng ta sẽ không thêm phần tử vào cuối danh sách, giống như thực hiện với ngăn xếp. Chúng tôi muốn chèn mục vào chỉ mục thứ 0 của danh sách, hay nói cách khác là vị trí đầu tiên của danh sách. Lý do chúng tôi làm điều đó là vì chúng tôi muốn lưu phần cuối của danh sách để bật ra các mục và sử dụng phần đầu của danh sách để chèn

class Queue:
    def __init__[self]:
        self.items = []

    def enqueue[self, item]:
        self.items.insert[0, item]

    def dequeue[self]:
        pass

    def size[self]:
        pass

    def peek[self]:
        pass

    def is_empty[self]:
        pass

Chúng ta có thể quay lại thiết bị đầu cuối để kiểm tra điều này trong trình bao Python tương tác. Trước tiên, chúng tôi tạo một đối tượng Hàng đợi và sau đó liệt kê một mục vào đó. Đầu tiên, chúng ta đặt chuỗi ‘Got in line first’ vào hàng đợi. Đây sẽ là mục đầu tiên được xử lý từ hàng đợi. Sau đó, chúng tôi thêm một chuỗi khác 'Second in line'. Cuối cùng, chúng tôi thêm chuỗi 'Last in line'. Bây giờ chúng tôi có thể kiểm tra nội dung của các mục và chúng tôi có thể thấy rằng chúng theo đúng thứ tự. Nếu đây là một hàng tại cửa hàng, các mặt hàng bên phải sẽ được xử lý trước

dequeue[]

Bây giờ hãy tạo phương thức dequeue[] sẽ giúp chúng ta lấy các mục ra khỏi hàng đợi. Phía trước của hàng đợi thực sự là phần cuối của danh sách. Vì đây là trường hợp, chúng tôi có thể sử dụng phương thức pop[] tích hợp sẵn của danh sách và chúng tôi sẽ luôn lấy lại phần tử đầu tiên của hàng đợi vì phương thức pop luôn trả về phần tử cuối cùng trong danh sách. Tuy nhiên, trước khi cố gắng lấy các mục ra khỏi hàng đợi, bạn nên đảm bảo rằng có một số mục cần xử lý từ hàng đợi. Nếu bạn cố bật một hàng đợi trống, bạn sẽ gặp lỗi

class Queue:
    def __init__[self]:
        self.items = []

    def enqueue[self, item]:
        self.items.insert[0, item]

    def dequeue[self]:
        if self.items:
            return self.items.pop[]
        else:
            return None

    def size[self]:
        pass

    def peek[self]:
        pass

    def is_empty[self]:
        pass

Một lần nữa, chúng tôi sẽ kiểm tra điều này trong trình thông dịch Python tương tác. Chúng tôi tạo một Hàng đợi mới, sau đó thêm một số mục vào đó. Đây là các chuỗi 'Đầu tiên', 'Thứ hai' và 'Thứ ba'. Chúng tôi xác nhận các mục hiện đang ở trong hàng đợi và theo thứ tự chúng tôi mong đợi. Bây giờ, khi chúng ta bắt đầu gọi phương thức dequeue[], mục ngoài cùng bên phải hoặc đầu tiên sẽ được xử lý. Chúng tôi thấy rằng đây là trường hợp và khi tiếp tục gọi phương thức dequeue[], các mục trong hàng đợi được xử lý giống như một dòng tại cửa hàng tạp hóa

kích thước[]

Phương thức size[] của lớp Queue thực sự khá dễ dàng. Tất cả những gì nó cần làm là trả về độ dài của các mục trong danh sách hàng đợi

class Queue:
    def __init__[self]:
        self.items = []

    def enqueue[self, item]:
        self.items.insert[0, item]

    def dequeue[self]:
        if self.items:
            return self.items.pop[]
        else:
            return None

    def size[self]:
        return len[self.items]

    def peek[self]:
        pass

    def is_empty[self]:
        pass

Kiểm tra phương thức size[] cho thấy nó hoạt động bình thường

nhìn lén[]

Phương pháp này được sử dụng khi chúng ta chỉ muốn xem mục tiếp theo trong hàng đợi sẽ được xử lý tiếp theo là gì. Tất cả những gì cần làm là trả lại mục cuối cùng trong danh sách vì mục cuối cùng trong danh sách là mục sẽ bị xóa tiếp theo. Để đảm bảo bạn không nhận được lỗi chỉ mục danh sách ngoài phạm vi, bạn sẽ muốn kiểm tra xem có mục nào để xem trước khi xem không. Chúng tôi có thể xử lý tình huống này trong mã của mình bằng cách nói rằng miễn là có các mục trong danh sách hiển thị cho chúng tôi mục cuối cùng trong danh sách. Điều này hoạt động hơi giống dequeue[] nhưng sự khác biệt là peek[] giữ nguyên hàng đợi, trong khi dequeue[] thực sự đang xử lý hoặc xóa một mục khi nó được gọi

class Queue:
    def __init__[self]:
        self.items = []

    def enqueue[self, item]:
        self.items.insert[0, item]

    def dequeue[self]:
        if self.items:
            return self.items.pop[]
        else:
            return None

    def size[self]:
        return len[self.items]

    def peek[self]:
        if self.items:
            return self.items[-1]
        else:
            return None

    def is_empty[self]:
        pass

is_empty[]

Phương thức cuối cùng chúng ta sẽ xem xét để xác định xem hàng đợi có trống hay không. Điều này được thực hiện bằng cách đơn giản trả về một kiểm tra bình đẳng của self. mục == []. Nói cách khác, nếu các mục bằng một danh sách trống, thì True được trả về. Nếu các mục không bằng một danh sách trống, Sai được trả về

class Queue:
    def __init__[self]:
        self.items = []

    def enqueue[self, item]:
        self.items.insert[0, item]

    def dequeue[self]:
        if self.items:
            return self.items.pop[]
        else:
            return None

    def size[self]:
        return len[self.items]

    def peek[self]:
        if self.items:
            return self.items[-1]
        else:
            return None

    def is_empty[self]:
        return self.items == []

Ví dụ về hàng đợi in

Với kiến ​​thức mới của chúng ta về cách hoạt động của Hàng đợi, hãy xem xét một tình huống thực tế hơn, nơi một người có thể gặp phải hàng đợi. Hãy suy nghĩ về thời điểm bạn in tài liệu bằng máy in dùng chung. Nếu có lệnh in trước của bạn, có thể mất một chút thời gian trước khi lệnh in của bạn được xử lý. Đó là cách hàng đợi hoạt động. Bạn phải xếp hàng ở cuối và đợi những người trước mặt bạn được xử lý. Đoạn mã sau cho thấy cách bạn có thể triển khai hàng đợi để in bằng ba lớp Python có tên PrintJob, PrintQueue và Printer. Lớp PrintQueue sử dụng các phương thức xếp hàng quen thuộc của enqueue[], dequeue[] và is_empty[]. Đối với lớp PrintJob, có một số logic xác định số lượng trang còn lại để in. Trong ví dụ này, chúng tôi chỉ in tối đa 5 trang. Nếu một trang được in, thì số trang sẽ giảm đi và khi không còn trang nào nữa, quá trình in sẽ kết thúc. Lớp Máy in có logic để hiểu PrintJob mà nó hiện đang làm việc. Các lớp này tương tác với nhau vì lớp Máy in có thể nhận công việc tiếp theo bằng cách xếp hàng từ một đối tượng PrintQueue không trống

import random


class PrintQueue:

    def __init__[self]:
        self.items = []

    def __str__[self]:
        pass

    def enqueue[self, item]:
        self.items.insert[0, item]

    def dequeue[self]:
        return self.items.pop[]

    def is_empty[self]:
        return self.items == []


class PrintJob:

    def __init__[self]:
        self.pages = random.randint[1, 6]

    def __str__[self]:
        return f'PrintJob[{self.pages}]'

    def print_page[self]:
        if self.pages > 0:
            self.pages -= 1

    def check_complete[self]:
        if self.pages == 0:
            return True
        return False


class Printer:

    def __init__[self]:
        self.current_job = None

    def get_job[self, print_queue]:
        try:
            self.current_job = print_queue.dequeue[]
        except IndexError:
            return "No more jobs to print."

    def print_job[self, job]:
        while job.pages > 0:
            job.print_page[]

        if job.check_complete[]:
            return "Printing complete."
        else:
            return "An error occurred."

Đây là mã đang hoạt động. Chúng tôi thiết lập hai lệnh in của j1 và j2. Sau đó, chúng tôi khởi tạo một hàng đợi in. sử dụng hàng đợi, chúng tôi liệt kê hai công việc vào hàng đợi in. Bây giờ chúng ta thiết lập một đối tượng máy in thông qua lớp Printer[]. Để có lệnh in đầu tiên, chúng ta gọi máy in. phương thức get_job[] trong khi tự chuyển vào hàng đợi. Từ đó, chúng tôi in công việc hiện tại bằng máy in. phương thức print_job[] trong khi chuyển vào công việc hiện tại. Chúng ta có thể thấy rằng công việc đầu tiên này chỉ có 1 trang và đã được in ra thành công. Điều tiếp theo cần làm là lấy công việc tiếp theo trong hàng đợi và in công việc đó ra. Chúng tôi thấy 5 trang được in ra. Cuối cùng, chúng tôi cố gắng nhận thêm bất kỳ công việc nào từ hàng đợi, nhưng chúng tôi thấy rằng không còn công việc nào để in vì chúng tôi đã làm trống hàng đợi

Tóm tắt ví dụ về hàng đợi Python

Trong hướng dẫn này, chúng ta đã tìm hiểu về hàng đợi là kiểu dữ liệu trừu tượng hoặc cấu trúc dữ liệu tuyến tính. Chúng ta đã thấy cách tạo hàng đợi bằng cách sử dụng các lớp Python và sau đó là cách triển khai kịch bản hàng đợi trong thế giới thực bằng cách sử dụng ví dụ về In. Các ứng dụng khác của hàng đợi trong khoa học máy tính bao gồm phục vụ các yêu cầu trên một tài nguyên dùng chung, chẳng hạn như tác vụ CPU hoặc ứng dụng phần mềm trung tâm cuộc gọi sử dụng Hàng đợi để giữ những người gọi họ theo thứ tự, cho đến khi đại diện dịch vụ rảnh. Bạn chắc chắn đã nghe tin nhắn, cuộc gọi của bạn sẽ được trả lời theo thứ tự nhận được. Một ví dụ khác có thể là việc xử lý các ngắt trong hệ thống thời gian thực. Các ngắt được xử lý theo thứ tự khi chúng đến. Đường một chiều cũng là một ví dụ về hàng đợi trong đó ô tô đầu tiên đi vào đường một chiều cũng là ô tô đầu tiên ra khỏi đường một chiều. Bạn hiểu ý, nhưng một ví dụ cuối cùng về hàng đợi là tòa nhà rửa xe tự động. Chiếc xe đầu tiên vào tòa nhà và được rửa sạch cũng là chiếc xe đầu tiên ra khỏi tòa nhà sạch bóng

Chủ Đề