Python 使用 win32print 打印 pdf 文件

问题描述 投票:0回答:3

我正在尝试使用模块

win32print
从 Python 打印 pdf 文件,但我可以打印成功的唯一方法是文本。

hPrinter = win32print.OpenPrinter("\\\\Server\Printer")
filename = "test.pdf"
try:
    hJob = win32print.StartDocPrinter(hPrinter, 1, ('PrintJobName', None, 'RAW'))
    try:
        win32api.ShellExecute(0, "print", filename, None, ".", 0)
        win32print.StartPagePrinter(hPrinter)
        win32print.WritePrinter(hPrinter, "test")  # Instead of raw text is there a way to print PDF File ?
        win32print.EndPagePrinter(hPrinter)
    finally:
        win32print.EndDocPrinter(hPrinter)
finally:
    win32print.ClosePrinter(hPrinter)

因此,我需要打印“test.pdf”文件,而不是打印文本。

我也尝试过使用

win32api.ShellExecute(0, "print", filename, None,  ".",  0)
但它不起作用,经过一些测试(例如(getprinter,getdefault,setprinter,setdefaultprinter))它似乎没有连接打印机。所以这样我就没法工作了。

这是我使用的代码!

win32print.SetDefaultPrinter(hPrinter)
win32api.ShellExecute(0, "print", filename, None,  ".",  0)
python python-3.x windows pdf printing
3个回答
17
投票

我想要一个能够每天打印大约 100 个 pdf 文件的解决方案 每约 200 页长。文件存储在特定目录中。

import win32api
import win32print
from glob import glob

# A List containing the system printers
all_printers = [printer[2] for printer in win32print.EnumPrinters(2)]
# Ask the user to select a printer
printer_num = int(input("Choose a printer:\n"+"\n".join([f"{n} {p}" for n, p in enumerate(all_printers)])+"\n"))
# set the default printer
win32print.SetDefaultPrinter(all_printers[printer_num])
pdf_dir = "D:/path/to/pdf_dir/**/*"
for f in glob(pdf_dir, recursive=True):
    win32api.ShellExecute(0, "print", f, None,  ".",  0)

input("press any key to exit")

备注:

  1. 您可以使用 DevMode 对象(GUI 代码上的示例)更改打印机属性,例如颜色/黑色、缩放比例、质量等。
  2. 提供文件名的绝对路径
  3. 在退出脚本之前给予足够的时间来处理作业。

虽然不是直接回答问题,但我无法抗拒使用

tkinter
制作 GUI 的机会。可以轻松更改它以选择一个目录 - 以及其中的所有文件 - 而不是单个文件。

import win32api
import win32print
import traceback

from tkinter.filedialog import askopenfilename
from tkinter import *
from tkinter import font # * doesn't import font or messagebox
from tkinter import messagebox

root = Tk()
root.title("Python Printer")
root.geometry("410x310")
root.resizable(False, False)
root.tk.call('encoding', 'system', 'utf-8')

def font_size(fs):
    return font.Font(family='Helvetica', size=fs, weight='bold')

# Add a grid
mainframe = Frame(root)
#mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.grid(column=0,row=0, sticky=(N) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 10, padx = 0)

# Create a _printer variable
_printer = StringVar(root)
# Create a _color variable
_color = StringVar(root)
_filename = ""

# on change dropdown value
def sel_printer(*args):
    print( _printer.get() )
# link function to change dropdown
_printer.trace('w', sel_printer)

def sel_color(*args):
    print( _color.get() )
# link function to change dropdown
_color.trace('w', sel_color)

def UploadAction(event=None):
    global _filename
    # _filename = filedialog.askopenfilename() - pre python 3.6.8
    _filename = askopenfilename() # post python 3.6.8
    #print('Selected:', _filename)
    
def PrintAction(event=None):

    PRINTER_DEFAULTS = {"DesiredAccess":win32print.PRINTER_ALL_ACCESS} 
    pHandle = win32print.OpenPrinter(_printer.get(), PRINTER_DEFAULTS)
    properties = win32print.GetPrinter(pHandle, 2)
    properties['pDevMode'].Color = 1 if str(_color.get()) == "Color" else 2
    properties['pDevMode'].Copies = 1
    win32print.SetPrinter(pHandle, 2, properties, 0)

    if not _filename:
        messagebox.showerror("Error", "No File Selected")
        return
    elif not _printer.get():
        messagebox.showerror("Error", "No Printer Selected")
        return
        
    try:
        #win32print.SetDefaultPrinter(_printer.get())
        win32api.ShellExecute(0, "print", _filename, None,  ".",  0)
        win32print.ClosePrinter(pHandle)
    except:
        pass
        messagebox.showerror("Error", "There was an error printing the file :(")

choices = [printer[2] for printer in win32print.EnumPrinters(2)]
_printer.set(win32print.GetDefaultPrinter()) # set the default option

popupMenu = OptionMenu(mainframe, _printer, *choices)
popupMenu['font'] = font_size(12)
Label(mainframe, text="SELECT PRINTER").grid(row = 1, column = 1)
popupMenu.grid(row = 2, column =1)

# Dictionary with options
choices = ["COLOR", "MONOCHROME"]
_color.set("COLOR") # set the default option

popupMenu2 = OptionMenu(mainframe, _color, *choices)
popupMenu2['font'] = font_size(12)
Label(mainframe, text="COLOR MODE").grid(row = 3, column = 1)
popupMenu2.grid(row = 4, column =1)

Label(mainframe, text="SELECT FILE").grid(row = 5, column = 1)
button = Button(mainframe, text=u"\uD83D\uDCC1" ' BROWSE', command=UploadAction)
button['font'] = font_size(12)
button.grid(row = 6, column =1)


_copies = IntVar()
_copies.set(1)

def copies_increase(event=None):
    _copies.set(_copies.get() + 1)
    
def copies_decrease(event=None):
    _copies.set(_copies.get() - 1)
    if _copies.get() < 1 :
        _copies.set(1)

Label(mainframe, textvariable=_copies).grid(columnspan=2)
button_frame = Frame(mainframe)
button_frame.grid(columnspan=2)


dec_button = Button(button_frame, text=u"\u2212", command=copies_decrease, fg="dark green", bg = "white", height=1, width=3 )
dec_button['font'] = font_size(10)

inc_button = Button(button_frame, text=u"\uFF0B", command=copies_increase, fg="dark green", bg = "white", height=1, width=3 )
inc_button['font'] = font_size(10)

button_frame.columnconfigure(0, weight=1)
button_frame.columnconfigure(1, weight=1)

dec_button.grid(row=0, column=0, sticky=W+E)
inc_button.grid(row=0, column=1, sticky=W+E)

Label(mainframe).grid(row = 10, column = 1)
p_button = Button(mainframe, text=u'\uD83D\uDDB6' + " PRINT", command=PrintAction, fg="dark green", bg = "white")
p_button['font'] = font_size(18)
p_button.grid(row = 11, column =1)

root.mainloop()

胃肠道


来源:

  1. Python 在我的 Brother 激光打印机上打印 pdf 文件(双面打印开/关)
  2. Python 使用 win32print 打印 pdf 文件
  3. http://docs.activestate.com/activepython/3.1/pywin32/PyDEVMODE.html
  4. https://www.thecodingforums.com/threads/printing-using-python.502484/
  5. https://stackoverflow.com/a/37586129/797495
  6. https://stackoverflow.com/a/56638762/797495
  7. https://t.codebug.vip/questions-712908.htm
  8. 如何在 Python Tkinter 中创建一个按钮来将整数变量加 1 并显示该变量?
  9. https://gregcaporale.wordpress.com/2012/01/18/powershell-to-print-files-automatically/这也可能是一个解决方案

PS:我可能不会赢得赏金,但我确实很喜欢制作 GUI。

tkinter
布局是最难的部分!

编辑:截至 2024 年,导入

from tkinter.filedialog import askopenfilename
的用法为
askopenfilename
;不是
filedialog.askopenfilename
。这似乎在 Python 3.6.8+ 版本的某个时候发生了变化。


5
投票

这是我使用过的代码,它工作正常。

name = win32print.GetDefaultPrinter() # verify that it matches with the name of your printer
printdefaults = {"DesiredAccess": win32print.PRINTER_ALL_ACCESS} # Doesn't work with PRINTER_ACCESS_USE
handle = win32print.OpenPrinter(name, printdefaults)
level = 2
attributes = win32print.GetPrinter(handle, level)
#attributes['pDevMode'].Duplex = 1  #no flip
#attributes['pDevMode'].Duplex = 2  #flip up
attributes['pDevMode'].Duplex = 3   #flip over
win32print.SetPrinter(handle, level, attributes, 0)
win32print.GetPrinter(handle, level)['pDevMode'].Duplex
win32api.ShellExecute(0,'print','manual1.pdf','.','/manualstoprint',0)

1
投票

你可以试试

win32print.SetDefaultPrinter("\\\\Server\Printer")

此方法接受一个字符串,而不是您尝试传递它的打印机对象。

© www.soinside.com 2019 - 2024. All rights reserved.