12

何百ものODTファイルをPDFファイルに変換していますが、次々と実行するのに長い時間がかかります。複数のコアを搭載したCPUがあります。bashまたはpythonを使用して、これらを並行して実行するスクリプトを作成することは可能ですか?コマンドラインからlibreofficeを使用してバッチドキュメント変換を並列化する方法はありますか(正しい単語を使用しているかどうかはわかりません)?私は次のコマンドを呼び出してpython/bashでそれを行っています:

libreoffice --headless --convert-to pdf *appsmergeme.odt

また

subprocess.call(str('cd $HOME; libreoffice --headless --convert-to pdf *appsmergeme.odt'), shell=True);

ありがとうございました!

ティム

4

6 に答える 6

4

libreofficeをデーモン/サービスとして実行できます。次のリンクを確認してください。おそらくそれも役立つでしょう:LibreOfficeサービスをデーモン化する

他の可能性は、unoconvを使用することです。「unoconvは、OpenOfficeがインポートできる任意のファイル形式をOpenOfficeがエクスポートできる任意のファイル形式に変換できるコマンドラインユーティリティです。」

于 2013-03-06T21:12:34.517 に答える
1

このスレッドまたは回答は古いです。libreoffice 4.4をテストしましたが、libreofficeを同時に実行できることを確認できました。私のスクリプトを参照してください。

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

于 2015-11-13T00:09:21.753 に答える
1

著者はすでにPythonを有効な答えとして紹介しているので:

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

multiprocessing.dummyとにかく、実際の並列処理のための新しいプロセスが生成されるため、プロセスプールの代わりにスレッドプールを使用するだけで十分subprocess.call()です。

コマンドと現在の作業ディレクトリcwdを直接設定できます。shellそれを行うためにファイルごとにをロードする必要はありません。さらに、os.pathクロスプラットフォームの相互運用性を可能にします。

于 2017-06-13T08:49:35.747 に答える
0

何千ものdoc/xlsファイルをバッチ変換するプログラムをgolangで作成しました。

  • 変換するドキュメントのパスに「root」変数値を定義します
  • すでにpdfに変換されたドキュメントはスキップされます(そうでない場合は、visit()関数でチェック条件をコメントしてください)
  • ここでは4つのスレッドを使用しています(4コアのIntel i3を使用しています)。main()関数で値を変更できます

Libreofficeが一部のファイルを変換しない場合があるため、ファイルを開いて手動でPDFに変換する必要があります。幸いなことに、変換するのは私の16.000ドキュメントのうち10だけでした。

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()
}
于 2016-04-05T09:01:19.737 に答える
0

unoconvでも同様の問題が発生しました。unoconvは内部的にlibreofficeを利用しています。1回の呼び出しで複数のファイルをunoconvに送信することで解決しました。したがって、すべてのファイルを反復処理する代わりに、ファイルのセットをバケットに分割します。各バケットはo/p形式を表します。次に、バケットと同じ数の呼び出しを行います。

libreofficeにも同様のモードがあると確信しています。

于 2017-06-13T08:10:01.110 に答える
-2

未テストの潜在的に有効:

あなたは/かもしれない/できる:

  • ファイルをいくつかの並列バッチに公平な方法で分割します。たとえば、すべてをフォルダーに配置します。
  • 各フォルダを処理するための個別のローカルユーザーアカウントを作成します。
  • Libreofficeを各ユーザーとしてシリアルに実行する

例えば

 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

を使用su -することで、実際のセッションから環境変数を誤って継承することがないため、並列プロセスが相互に干渉することはありません(リソースの競合を除く)。

これらはI/Oバウンドのタスクである可能性が高いため、CPUコアごとに1つ実行しても、それほど高速化されない可能性があることに注意してください。

于 2013-03-06T21:16:43.743 に答える