2013-02-27 10 views
9

Konwertuję setki plików ODT na pliki PDF, a wykonanie wielu z nich zajmuje dużo czasu. Mam procesor z wieloma rdzeniami. Czy można użyć skryptu bash lub Python do napisania skryptu, aby zrobić to równolegle? Czy istnieje sposób równoległego (nie wiem, czy używam właściwego słowa) konwersji dokumentu wsadowego przy użyciu libreoffice z wiersza poleceń? robiłem go w Pythonie/bash nazywając następujące polecenia:Równoległa konwersja dokumentów ODT> PDF Libreoffice

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

LUB

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

Dziękujemy!

Tim

+0

Czy chcesz uruchomić pojedyncze polecenie 'libreoffice' na wielu procesorach lub wykonywać wiele połączeń z' libreoffice' i konwertować pliki osobno? W pierwszym przypadku nie można nic zrobić, w drugim przypadku jest to proste. – Bakuriu

+2

Uhm, wierzę, że 'libreoffice' zapobiega równoczesnemu uruchomieniu więcej niż jednego konwertera PDF. Próba utworzenia wielu procesów powoduje wygenerowanie pojedynczego pliku '.pdf', a pozostałe procesy kończą się niepowodzeniem. Dzieje się tak nawet przy użyciu opcji '--nolockcheck'. Wierzę, że odpowiedź na twoje pytanie brzmi: nie możesz. Powinieneś użyć innego programu do konwersji. – Bakuriu

+0

Wierzę, że kiedyś czytałem, że libreoffice zawsze używa tylko jednego procesu (także w odniesieniu do pisarza, zaimponować itd.), Co prawdopodobnie uniemożliwiłoby to. – lolopop

Odpowiedz

3

LibreOffice można uruchomić jako demon/usługi. Sprawdź poniższy link, może to ci również pomoże: Daemonize the LibreOffice service

Inną możliwością użycia jest użycie unoconv. "unoconv to narzędzie wiersza poleceń, które potrafi konwertować dowolny format plików, który może importować OpenOffice, do dowolnego formatu pliku, który może eksportować OpenOffice."

-1

Nietestowane potencjalnie ważny:

Ty/może/mógł:

  • podzielić pliki na szereg równoległych seriach w jakiś sprawiedliwy sposób, na przykład umieszczając je wszystkie w folderach;
  • Utwórz odrębne lokalne konto użytkownika do obsługi każdego folderu;
  • uruchomić libreoffice szeregowo ponieważ każdy użytkownik

np

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 

Korzystając su - nie będzie przypadkowo dziedziczyć żadnych zmiennych środowiskowych z prawdziwego sesji, więc równoległe procesy nie powinny kolidować ze sobą (oprócz konkurowania o zasoby).

Należy pamiętać, że są to najprawdopodobniej związane z I/O zadania, więc uruchomienie 1 na rdzeń procesora prawdopodobnie nie zaowocuje ani tak bardzo.

+0

Open/Libreoffice nie pozwala na równoległe uruchamianie soffice.exe – luca76

0

ten wątek lub odpowiedź jest stara. Testowałem libreoffice 4.4, mogę potwierdzić, że mogę jednocześnie uruchomić libreoffice. zobacz mój skrypt.

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

0

Napisałem program w golang na konwertowanie tysięcy plików doc/xls.

  • określenie „root” zmienną wartość ścieżki dokumentów do konwersji
  • już przekształcane dokumenty PDF są pomijane (jeśli nie, komentarz warunek wyboru w funkcji wizyty())
  • tutaj Używam 4 wątków (mam Intel i3 z 4 rdzeniami). Możesz zmodyfikować wartość w funkcji głównej()

Czasami może się zdarzyć, że Libreoffice nie konwertuje niektórych plików, więc powinieneś otworzyć i przekonwertować je na PDF ręcznie. Na szczęście, udało mi się przekonwertować tylko 10 z 16 000 moich dokumentów.

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

Mieliśmy podobny problem z unoconv. unoconv wewnętrznie korzysta z libreoffice. Rozwiązaliśmy go, wysyłając wiele plików do unoconv w jednym wywołaniu. Tak więc, zamiast powtarzania wszystkich plików, po prostu dzielimy zestaw plików na segmenty, przy czym każde wiadro reprezentuje format o/p. Następnie wykonujemy tyle połączeń, ile jest wiaderek.

Jestem całkiem pewny, że libreoffice ma również podobny tryb.

0

Ponieważ autor już wprowadzone Python jako ważnego odpowiedź:

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

Korzystanie z puli wątków zamiast basenu procesowego przez multiprocessing.dummy jest wystarczające, ponieważ nowe procesy realnego równoległości są tarło przez subprocess.call() tak.

Możemy ustawić polecenie, jak również bieżący katalog roboczy cwd bezpośrednio. Nie ma potrzeby ładowania pliku shell dla każdego pliku, aby to zrobić. Ponadto, os.path umożliwia współdziałanie między platformami.