Parallel Document Conversion ODT > PDF Libreoffice

后端 未结 6 1578
别跟我提以往
别跟我提以往 2021-02-05 22:41

I am converting hundreds of ODT files to PDF files, and it takes a long time doing one after the other. I have a CPU with multiple cores. Is it possible to use bash or python to

相关标签:
6条回答
  • 2021-02-05 22:55

    We had a similar problem with unoconv. unoconv internally makes use of libreoffice. We solved it by sending multiple files to unoconv in one invocation. So, instead of iterating over all files, we just partition the set of files into buckets, each bucket representing the o/p format. Then we make as many calls as there are buckets.

    I am pretty sure libreoffice also has a similar mode.

    0 讨论(0)
  • 2021-02-05 22:58

    Untested potentially valid:

    You /may/ be able to:

    • Divide up the files into a number of parallel batches in some equitable way, e.g. placing them all in folders;
    • Create a distinct local user account to handle each folder;
    • Run Libreoffice serially as each user

    e.g.

     for paralleluser in timlev1 timlev2 timlev3 timlev4 ; do
          su - $paralleluser -c \
             "for file in /var/spool/pdfbatches/$paralleluser ; do \
                libreoffice --headless --convert-to pdf $file ; done" 
     done
    

    By using su - you won't accidentally inherit any environment variables from your real session, so the parallel processes shouldn't interfere with one another (aside from competing for resources).

    Keep in mind, these are likely I/O-bound tasks, so running 1 per CPU core will probably not speed you up so very much.

    0 讨论(0)
  • 2021-02-05 23:03

    this thread or answer is old. I tested libreoffice 4.4, I can confirm I can run libreoffice concurrently. see my script.

    for odt in test*odt ; do
    echo $odt
    soffice --headless --convert-to pdf $odt & 
    ps -ef|grep ffice 
    done

    0 讨论(0)
  • 2021-02-05 23:07

    I've written a program in golang to batch convert thousands of doc/xls files.

    • define the "root" variable value to the path of your documents to convert
    • already converted documents to pdf are skipped (if not, comment the check condition in the visit() function)
    • here I'm using 4 threads (I have an Intel i3 with 4 cores). You can modify the value in the main() function

    Sometimes it can happen that Libreoffice doesn't convert some files, so you should open it and convert them to PDF manually. Luckily, they were only 10 out of my 16.000 documents to convert.

    package main
    
    import (
        "os/exec"
        "sync"
        "path/filepath"
        "os"
        "fmt"
        "strings"
    )
    
    // root dir of your documents to convert
    root := "/.../conversion-from-office/"
    
    var tasks = make(chan *exec.Cmd, 64)
    
    func visit(path string, f os.FileInfo, err error) error {
        if (f.IsDir()) {
            // fmt.Printf("Entering %s\n", path)
        } else {
            ext := filepath.Ext(path)
            if (strings.ToLower (ext) == "pdf") {
            } else {
    
    
                outfile := path[0:len(path)-len(ext)] + ".pdf"
    
                if _, err := os.Stat(outfile); os.IsNotExist(err) {
    
                    fmt.Printf("Converting %s\n", path)
    
                    outdir := filepath.Dir(path)
                    tasks <- exec.Command("soffice", "--headless", "--convert-to", "pdf", path, "--outdir", outdir)
                }
            }
        }
        return nil
    } 
    
    
    func main() {
        // spawn four worker goroutines
        var wg sync.WaitGroup
    
        // the  ...; i < 4;... indicates that I'm using 4 threads
        for i := 0; i < 4; i++ {
            wg.Add(1)
            go func() {
                for cmd := range tasks {
                    cmd.Run()
                }
                wg.Done()
            }()
        }
    
    
        err := filepath.Walk(root, visit)
        fmt.Printf("filepath.Walk() returned %v\n", err)
    
        close(tasks)
    
        // wait for the workers to finish
        wg.Wait()
    }
    
    0 讨论(0)
  • 2021-02-05 23:10

    You can run libreoffice as a daemon/service. Please check the following link, maybe it helps you too: Daemonize the LibreOffice service

    Other posibility is to use unoconv. "unoconv is a command line utility that can convert any file format that OpenOffice can import, to any file format that OpenOffice is capable of exporting."

    0 讨论(0)
  • 2021-02-05 23:12

    Since the author already introduced Python as a valid answer:

    import subprocess
    import os, glob
    from multiprocessing.dummy import Pool    # wrapper around the threading module
    
    def worker(fname, dstdir=os.path.expanduser("~")):
        subprocess.call(["libreoffice", "--headless", "--convert-to", "pdf", fname],
                        cwd=dstdir)
    
    pool = Pool()
    pool.map(worker, glob.iglob(
            os.path.join(os.path.expanduser("~"), "*appsmergeme.odt")
        ))
    

    Using a thread pool instead of a process pool by multiprocessing.dummy is sufficient because new processes for real parallelism are spawn by subprocess.call() anyway.

    We can set the command as well as the current working directory cwd directly. No need to load a shell for each file for just doing that. Furthermore, os.path enables cross-platform interoperability.

    0 讨论(0)
提交回复
热议问题