添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Python静默打印PDF到特定的打印机

21 人关注

我有一个PDF文档,我想用我的Python应用程序来打印它。

我已经尝试了在 here (Print PDF document with python's win32print module?) 但当我安装Ghostscript 9.15这个实际版本时,它没有 gsprint.exe

我使用的方法是使用命令 os.startfile('PDFfile.pdf', "print") ,但它打开了默认的查看器(我的是Adobe Reader),并且在打印后它仍然打开,试图用 os.system("TASKKILL /F /IM AcroRD32.exe") 杀死这个进程会杀死其他打开的窗口,我不希望这样。

用下一个命令,它也能打印,但它让Adobe Reader也打开了

currentprinter = win32print.GetDefaultPrinter()
win32api.ShellExecute(0, "print", 'PDFfile.pdf', '/d:"%s"' % currentprinter, ".", 0)

我已经看到这个答案也是,但他们建议再使用gsprint.exe

有没有人有gsprint.exe文件或任何其他解决方案?

NOTE:当我用另一个默认程序打开PDF文件时,如Chrome或Windows Reader,我总是在执行上面的'(31, 'ShellExecute', 'A device attached to the system is not functioning.')'[Error 1155] No application is associated with the specified file for this operation: 'PDFfile.pdf'命令时得到一个异常。

python
pdf
printing
Alex Lord Mordor
Alex Lord Mordor
发布于 2014-11-29
9 个回答
Alex Lord Mordor
Alex Lord Mordor
发布于 2022-08-17
已采纳
0 人赞同

经过几个小时的搜索,我终于找到了问题的答案。

你可以在以下网站下载GSPRINT HERE

你可以在以下网址下载Ghostscript GPL HERE

在你的电脑(Windows)上有了这些提取的文件,你可以用这个命令打印你的PDF文件

GHOSTSCRIPT_PATH = "C:\\path\\to\\GHOSTSCRIPT\\bin\\gswin32.exe"
GSPRINT_PATH = "C:\\path\\to\\GSPRINT\\gsprint.exe"
# YOU CAN PUT HERE THE NAME OF YOUR SPECIFIC PRINTER INSTEAD OF DEFAULT
currentprinter = win32print.GetDefaultPrinter()
win32api.ShellExecute(0, 'open', GSPRINT_PATH, '-ghostscript "'+GHOSTSCRIPT_PATH+'" -printer "'+currentprinter+'" "PDFFile.pdf"', '.', 0)

也可以在官方网页上找到GhostScript。HERE

I found the gsprint.exe for 64bits HERE

I hope this helps.

用于64bits的gsprint.exe链接已经失效(2017年10月),但这个链接可以用于32bit。 pages.cs.wisc.edu/~ghost/gsview/gsprint.htm
对于windows来说,这是一个旧的链接,而ubuntu或linux不存在这个包,这是windows的具体答案。
这不是默默地打印文件--它打开一个窗口一秒钟左右,然后又关闭了!这是不可能的。
gsprint的链接已死,我找不到它了:(
这里是gsprint的一个新链接。 fossies.org/linux/misc/old/ghost/ghostgum
wetler
wetler
发布于 2022-08-17
0 人赞同

我知道这是个老问题了,但为了防止有人找它,我是这样解决的。

我在windows 10 64位上使用python 3.8和gs9.52以及python3-ghostscript库,你可以用 pip install python3-ghostscript 来安装。我还使用了pypiwin32来获取默认的打印机名称,你可以用pip pip install pypiwin32 来安装它。

This is the working script

import tempfile
import win32print
import locale
import ghostscript
import render_to_pdf
pdf = render_to_pdf('print/slip.html', context)
temp1 = tempfile.mktemp('.pdf')
f1 = open(temp1, 'ab')
f1.write(pdf)
f1.close()
args = [
        "-dPrinted", "-dBATCH", "-dNOSAFER", "-dNOPAUSE", "-dNOPROMPT"
        "-q",
        "-dNumCopies#1",
        "-sDEVICE#mswinpr2",
        f'-sOutputFile#"%printer%{win32print.GetDefaultPrinter()}"',
        f'"{temp1}"'
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
ghostscript.Ghostscript(*args)

有几件事需要注意,我使用'#'而不是'=',因为由于某些原因,使用'='无法工作。

如果这对你不起作用,请尝试将-sDEVICE开关改为你的打印机类型,例如,当我在使用惠普激光打印机它给了我提示,所以我把-sDEVICE改为laserjet,就成功了,你可以在终端运行gs -h来获得设备的列表

如果你已经有了要打印的pdf文件......你可以把 f'"{temp1}"' 这一行替换为 f'"{f}"' ,其中 f = os.path.join(os.getcwd(), 'testprint.pdf').replace('\\', '\\\\') 。当然一定要把 import os 放在顶部。如果你满足所有这些要求,你将不需要 args = [...] 以上的东西,直到 import ghostscript 行,看到 import render_to_pdf 没有在任何地方定义,你也不需要 import win32print 。谢谢你的这段伟大的代码
另外, , "-dFIXEDMEDIA", "-dPSFitPage", 作为额外的参数将有助于将内容放在页面的中心位置!
bdoubleu
bdoubleu
发布于 2022-08-17
0 人赞同

这里有一种方法,可以在与你的Python脚本相同的目录下默默地打印pdf,而不需要 gsprint win32api 。它允许更多的GhostScript定制,如选择宽度/高度等。

import os
import subprocess
import sys
if sys.platform == 'win32':
    args = '"C:\\\\Program Files\\\\gs\\\\gs9.23\\\\bin\\\\gswin64c" ' \
           '-sDEVICE=mswinpr2 ' \
           '-dBATCH ' \
           '-dNOPAUSE ' \
           '-dFitPage ' \
           '-sOutputFile="%printer%myPrinterName" '
    ghostscript = args + os.path.join(os.getcwd(), 'myFile.pdf').replace('\\', '\\\\')
    subprocess.call(ghostscript, shell=True)

If you're using the 32 bit version of GhostScript then you would use gswin32c

这不是默默地打印文件--它打开一个窗口一秒钟左右,然后又关闭了!这是不可能的。
@bdoubleu gswin64c gswin64 的区别是什么?谢谢
Jisson
Jisson
发布于 2022-08-17
0 人赞同

下面的代码将阻止当前的任务

for i in range(10):
    currentprinter = win32print.GetDefaultPrinter()
    win32api.ShellExecute(0, "print", 'PDFfile.pdf', '/d:"%s"' % currentprinter, ".", 0)

并且在打印完帮助后杀死阅读器不会阻止当前的任务。

os.system("TASKKILL /F /IM AcroRD32.exe") 

but it will close other pdf files too.

如果你不能使用gsprint,请使用acrobat命令

import win32print
import subprocess
import time
pdf_file  = 'D:\d1\d1.pdf'
acrobat = 'C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe'
name = win32print.GetDefaultPrinter()
cmd = '"{}" /n /o /t "{}" "{}"'.format(acrobat, pdf_file, name)
for i in range(10)):
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

它不会阻止当前的任务并关闭其他的pdf文件。

这对我的需求来说很有效,但是,即使在关闭窗口后,我的adobe acrobat仍然保持开放。 有什么办法可以确保它也能关闭?
试试下面的方法,cmd = '"{}"/n /o /t "{}""{}"'.format(acrobat, file_path, printer_name) proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = proc.communication() proc.terminate()
我似乎仍然不能使它发挥作用。 它关闭了带有pdf的文件,但adobe acrobat本身却保持开放。
试着模拟它,我想我不会再来了,对我来说,Adobe出现在任务栏里,在打开的状态下不会出现。
我相信,adobe一直在任务栏中打开,我们无法改变它。
Mohammad
Mohammad
发布于 2022-08-17
0 人赞同

如果你想打印特定的页面和其他一些参数,你应该在 gsprint 的参数中指定它们,如下所示。

import win32print
import win32api
GHOSTSCRIPT_PATH = "C:\\path\\to\\GHOSTSCRIPT\\bin\\gswin32.exe"
GSPRINT_PATH = "C:\\path\\to\\GSPRINT\\gsprint.exe"
params = '-ghostscript "'+ GHOSTSCRIPT_PATH  +'" -printer "'+currentprinter+'" -from 1 -to 3 -landscape -copies 1 "1.pdf "'
print(params)
win32api.ShellExecute(0, 'open', GSPRINT_PATH, params, '.',0)
    
Ryan
Ryan
发布于 2022-08-17
0 人赞同

所以这并不完全是静默的,但它会自动驳回对话框并打印,也有一个奇怪的对selenium的依赖,这本身是你想不到的,但这对我来说实际上是有效的,因为我在一个不允许下载ghostscript的世界里,也不能下载adobe的pdf阅读器。我想这可能会帮助其他人,在某个地方,某个时间......

from selenium import webdriver
import win32com.client
import win32print
import time
def printpdf(pdf,printer):
    current_printer = win32print.GetDefaultPrinter()
    win32print.SetDefaultPrinter(printer)
    driver = webdriver.Chrome()
    driver.get(pdf)
    time.sleep(1) #Adjust as necessary
    shell = win32com.client.Dispatch("WScript.Shell")
    shell.SendKeys('^p')
    time.sleep(1) #Adjust as necessary
    shell.SendKeys('{ENTER}') #dismiss the print dialog box
    driver.close()
    win32print.SetDefaultPrinter(current_printer)
    
Arthur
Arthur
发布于 2022-08-17
0 人赞同

根据之前的回答和其他帖子,我开发了以下脚本,从Laravel网站打印 .pdf .ps

I used python 3.9 and Ghostscript 9.54 (for 64bits). pywin32 and python3-ghostscript libs are requiered too.

import os
import sys
import win32print
import win32api
import ghostscript
import locale
USELESS_PRINTER = ['OneNote for Windows 10', 'OneNote (Desktop)', 'Microsoft XPS Document Writer',
                   'Microsoft Print to PDF', 'Fax']
HELP = """pyPrinter - Author: Arthur SICARD - Date: 19/05/2021
\n-help
\tDisplay this message.
\n-list [-virtual]
\tReturn list of available printer (excepted: """ + ", ".join(USELESS_PRINTER) + """)
\n-file filepath [-printer printer_name] [-virtual]
\tPrint specified file on default system printer. Use -printer to specify printer to use. Printer name must be available un -list response.
\n-batch filepath [-printer printer_name] [-virtual]
\tPrint each document specified un batch file on default system printer. Batch file must be a .txt. Each file to print must be write on its own line.
\tUse -printer to specify printer to use. Printer name must be available un -list response.
\n-virtual
\tUse this option after all other arguments to enable printing on virtual printer 'Microsoft Print to PDF'
# Safe accessor to argv. Return None if index is not set
def getArgv(index):
        return (sys.argv[1:])[index]
    except:
        return None
# Return list of local printer available without "virtual printer" define in USELESS_PRINTER list.
def getAvailablePrinters():
    printers = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL)
    printer_list = []
    for x in range(len(printers)):
        if printers[x][2] not in USELESS_PRINTER:
            printer_list.append(printers[x][2])
    return printer_list
# Return printer name to use. If -printer is set it will return this value only if value match with available
# printers list. Return a error if -printer not in list. If no printer specified, retrieve default printer and return
# its name. Sometime default printer is on USELESS_PRINTER list so first printer return by getAvailablePrinters() is
# return. If no printer is return display an error.
def getPrinter():
    default_printer = win32print.GetDefaultPrinter()
    if default_printer in USELESS_PRINTER:
        if len(getAvailablePrinters()) == 0:
            print("No printer available, unable to print. Use -virtual if you want enable virtual printer.")
            sys.exit(1801)
        default_printer = getAvailablePrinters()[0]
    if getArgv(2) is not None:
        if getArgv(2) == "-printer":
            printer = getArgv(3)
            if printer in getAvailablePrinters():
                return printer
            else:
                if printer is not None:
                    print("Given printer not found. Defaut printer configured: ", default_printer)
    return default_printer
# Use GhostScript API to silent print .pdf and .ps. Use win32api to print .txt. Return a error if printing failed or
# file ext doesn't match.
def printFile(filepath):
        if os.path.splitext(filepath)[1] in [".pdf", ".ps"]:
            args = [
                "-dPrinted", "-dBATCH", "-dNOSAFER", "-dNOPAUSE", "-dNOPROMPT"
                                                                  "-q",
                "-dNumCopies#1",
                "-sDEVICE#mswinpr2",
                f'-sOutputFile#"%printer%{getPrinter()}"',
                f'"{filepath}"'
            encoding = locale.getpreferredencoding()
            args = [a.encode(encoding) for a in args]
            ghostscript.Ghostscript(*args)
        elif os.path.splitext(filepath)[1] in [".txt"]:
            # '"%s"' % enable to encapsulate string with quote
            win32api.ShellExecute(0, "printto", '"%s"' % filepath, '"%s"' % getPrinter(), ".", 0)
        return True
    except:
        print("Printing error for file: ", '"%s"' % filepath, "| Printer: ", '"%s"' % getPrinter())
        return False
def main(argv):
    if len(argv) in [1, 2, 4, 5]:
        cmd1 = getArgv(0)
        filepath = getArgv(1)
        if argv[-1] == "-virtual":
            USELESS_PRINTER.remove('Microsoft Print to PDF')
        # Batch printing mode
        if cmd1 == "-batch" and len(argv) in [2, 4, 5]:
            if not os.path.isfile(filepath) and not os.path.exists(filepath):
                print("Path provide for batch file is not a valid file path or doesn't exist.")
                sys.exit(2)
            if os.path.splitext(filepath)[1] in [".txt"]:
                with open(filepath) as fp:
                    line = fp.readline().strip('\n')
                    while line:
                        if not os.path.isfile(line) and not os.path.exists(line):
                            print("Path provide is not a valid file path or doesn't exist: ", line)
                        else:
                            printFile(line)
                        line = fp.readline().strip('\n')
                fp.close()
            else:
                print("Not supported file format for batch printing.")
                sys.exit(50)
        # Single file printing mode
        elif cmd1 == "-file" and len(argv) in [2, 4, 5]:
            if not os.path.isfile(filepath) and not os.path.exists(filepath):
                print("Path provide is not a file path.")
                sys.exit(2)
            if not printFile(filepath):
                sys.exit(1)
        # Get printers list
        elif cmd1 == "-list" and len(argv) in [1, 2]:
            for printer in getAvailablePrinters():
                print(printer)
        # Display help
        elif cmd1 == "-help" and len(argv) in [1]:
            print(HELP)
            sys.exit(0)
        else:
            print("Unknow option. Use -help to obtain more informations about supported options.")
            sys.exit(50)
    else:
        print("Wrong arguments number. Use -help to obtain more informations about supported options.")
        sys.exit(50)
    exit(0)
if __name__ == '__main__':
    main(sys.argv[1:])

下面的命令解释了如何使用它。 【替换代码7

pyPrinter - Author: Arthur - Date: 19/05/2021
-help
    Display this message.
-list [-virtual]
    Return list of available printer (excepted: OneNote for Windows 10, OneNote (Desktop), Microsoft XPS Document Writer, Microsoft Print to PDF, Fax)
-file filepath [-printer printer_name] [-virtual]
    Print specified file on default system printer. Use -printer to specify printer to use. Printer name must be available un -list response.
-batch filepath [-printer printer_name] [-virtual]
    Print each document specified un batch file on default system printer. Batch file must be a .txt. Each file to print must be write on its own line.
    Use -printer to specify printer to use. Printer name must be available un -list response.
-virtual
    Use this option after all other arguments to enable printing on virtual printer 'Microsoft Print to PDF'

To print one file to printer HP1FF6CC (HP OfficeJet Pro 6970)

python main.py -file "D:\my\system\path\to\file\pattern.ps" -printer "HP1FF6CC (HP OfficeJet Pro 6970)"

打印一个文件到虚拟打印机 Microsoft Print to PDF(一般用于文本目的,纸张很快就会很贵)。

python main.py -file "D:\my\system\path\to\file\pattern.ps" -printer "Microsoft Print to PDF" -virtual

tttony
tttony
发布于 2022-08-17
0 人赞同

如果你有Adobe,可以试试这个。

import win32api
import winreg
import subprocess
import time
def get_adobe_executable():
    with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as conn:
        with winreg.OpenKey(conn, r'SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe', 0, winreg.KEY_READ) as hkey:
            value = winreg.QueryValue(hkey, None)
            if value:
                value = '"{}"'.format(value)
                return value.strip()
    return None
def print_pdf_file(file, printer_name=None, secs=5):
    cmd = get_adobe_executable()
    if cmd is None:
        return False
    if printer_name:
        cmd = '{} /h /t "{}" "{}"'.format(cmd, file, printer_name)
    else:
        cmd = '{} /p /h "{}"'.format(cmd, file)
    proc = subprocess.Popen(cmd)
    time.sleep(secs)
    proc.kill()
    return True
if __name__ == "__main__":
    print_pdf_file("doc.pdf") # print with default printer
    print_pdf_file("doc.pdf", "HP LaserJet Pro M102") # setting the printer name

get_adobe_executable

从注册表中获取Adobe(你也可以获取打印命令,就像你右击pdf文件并从菜单中选择打印一样,但我想只获取路径,然后根据打印机配置进行配置)。

print_pdf_file

如果你不设置printer_name变量,Adobe将使用默认打印机打印

在执行打印命令后,它将等待5秒钟,然后关闭Adobe程序,Adobe没有命令行选项(截至今天为止)在打印文件后退出。here你可以看到命令行选项

chanti
chanti
发布于 2022-08-17
0 人赞同

也有另一种方法可以在没有adobe reader的情况下将文件发送到打印机,由SumatraPDF提供。

安装SumatraPDF应用程序,并在路径中添加SumatraPDF.exe的位置。

# import subprocess and os
import subprocess
import os
# file path
file_name = "Document.pdf"
if file_name:
    print("exist")
# send data to the printer
    subprocess.call(['SumatraPDF.exe', '-print-to', "Barcode",
                     '-print-settings', "1x", file_name])
except BaseException as msg:
    print(msg)