簡體   English   中英

Python 靜默打印 PDF 到特定打印機

[英]Python silent print PDF to specific printer

我有一個 PDF 文檔,我想用我的 python 應用程序打印它。

我已經嘗試過這里的解決方案(使用 python 的 win32print 模塊打印 PDF 文檔?)但是當我安裝 Ghostscript 9.15 是實際版本時,它沒有gsprint.exe

我使用的方法是使用命令os.startfile('PDFfile.pdf', "print")但它會打開默認查看器(我的是 Adobe Reader),打印后它仍然打開,試圖用os.system("TASKKILL /F /IM AcroRD32.exe")進程os.system("TASKKILL /F /IM AcroRD32.exe")殺死其他打開的 windows 我不想要它。

使用下一個命令,它也會打印,但它也會讓 Adobe Reader 打開

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

我也看過這個答案,但他們建議再次使用gsprint.exe

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

注意:當我使用另一個默認程序打開 PDF 文件(如 Chrome 或 Windows 閱讀器)時,我總是在執行上面的命令時遇到異常'(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'使用startfile命令的“PDFfile.pdf”

最后,經過數小時的搜索正確的文件,我找到了問題的答案。

您可以在 此處下載 GSPRINT

您可以在此處下載 Ghostscript GPL

在您的 PC (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 也可以在此處的官方頁面中找到

我在這里找到了 64 位的 gsprint.exe

我希望這有幫助。

這是一種在沒有gsprintwin32api情況下gsprint與 python 腳本相同的目錄中靜默打印 pdf 的方法。 它允許更多的 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)

如果您使用的是 32 位版本的 GhostScript,那么您將使用gswin32c

以下代碼將阻塞當前任務

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") 

但它也會關閉其他 pdf 文件。

如果無法使用 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 文件。

我知道這是一個老問題,但如果有人在這里尋找它,我就是如何解決它的。

我在 Windows 10 64 位和 python3-ghostscript 庫上使用 python 3.8 和 gs9.52,您可以使用pip install python3-ghostscript我也使用 pypiwin32 來獲取默認打印機名稱,您可以使用 pip pip install pypiwin32安裝它pip install pypiwin32

這是工作腳本

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 開關更改為您的打印機類型,例如,當我使用HP LaserJet 時,它給了我提示,所以我將 -sDEVICE 更改為 Laserjet 並且它工作正常,您可以通過運行獲取設備列表終端中的gs -h

如果要打印特定頁面和其他一些參數,則應在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)

所以這並不是完全無聲的,但它會自動關閉對話框並無論如何打印,而且對硒有一種奇怪的依賴,你本身不會期望,但這實際上對我有用,因為我在一個世界中不允許下載 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)
    

    

根據之前的答案和其他帖子,我開發了以下腳本來從 Laravel 網站打印.pdf.ps

我使用了python 3.9Ghostscript 9.54 (用於 64 位)。 pywin32python3-ghostscript庫也是必需的。

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):
    try:
        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):
    try:
        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:])

以下命令解釋了如何使用它: python main.py -help

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'

將一個文件打印到打印機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

如果你有 Adob​​e 試試這個:

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 printer_name:
        cmd = '{} /h /t "{}" "{}"'.format(cmd, file, printer_name)
    else:
        cmd = '{} /p /h "{}"'.format(cmd, file)
    #print(cmd)
    proc = subprocess.Popen(cmd)
    time.sleep(secs)
    proc.kill()

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

從注冊表中獲取 Adob​​e(您也可以像右鍵單擊 pdf 文件並從菜單中選擇打印一樣獲取打印命令,但我只想獲取路徑然后根據打印機配置對其進行配置)

print_pdf_file

如果您不設置printer_name變量,Adobe 將使用默認打印機進行打印

執行打印命令后,它會等待 5 秒然后關閉 Adob​​e 程序,Adobe 沒有命令行選項(就像今天寫的那樣)打印文件后退出,在這里你可以看到命令行選項

SumatraPDF 還有另一種方法可以在沒有 adobe reader 的情況下將文件發送到打印機

安裝 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

try:
    subprocess.call(['SumatraPDF.exe', '-print-to', "Barcode",
                     '-print-settings', "1x", file_name])

except BaseException as msg:
    print(msg)

不需要任何 adobe 閱讀器,並且每次它不會打開 adobe 閱讀器來讀取數據,但問題是應該嘗試頁面方向和頁面大小,但如果 pdf 始終相同,我們可以更改直接打印打印機屬性,

僅將exe路徑添加到系統中的文件路徑在此處輸入圖像描述

而已

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM