[英]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
我希望這有幫助。
這是一種在沒有gsprint
和win32api
情況下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.9
和Ghostscript 9.54
(用於 64 位)。 pywin32
和python3-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
如果你有 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 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
從注冊表中獲取 Adobe(您也可以像右鍵單擊 pdf 文件並從菜單中選擇打印一樣獲取打印命令,但我只想獲取路徑然后根據打印機配置對其進行配置)
print_pdf_file
如果您不設置printer_name
變量,Adobe 將使用默認打印機進行打印
執行打印命令后,它會等待 5 秒然后關閉 Adobe 程序,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 始終相同,我們可以更改直接打印打印機屬性,
而已
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.