[GastForen Programmierung/Entwicklung AppleScript Skripteditor steigt aus beim Skriptablauf + Speicherproblem

  • Suche
  • Hilfe
  • Lesezeichen
  • Benutzerliste
Themen
Beiträge
Moderatoren
Letzter Beitrag

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Goar
Beiträge gesamt: 395

14. Apr 2005, 10:25
Beitrag # 1 von 7
Bewertung:
(1283 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Forum,

habe gerade meinen Umzug auf OSX begonnen:
iMac,10.3.8, 1.8 GHz G5, 1 GB; Skripteditor 2.0 (v43), D1-1.9.3


Mein Skript soll den Inhalt einer Text-Datei (formatierter Text) in eine Variable speichern und bearbeiten. Kleine Musterdateien und eine Originaldatei von 12 MB wurden zügig verarbeitet.

Das heißt, wenn das Skript nicht nach wenigen Sekunden ohne Angaben von Gründen ausstieg. Zunächst nahm ich an, das läge daran, dass ich das Skript mit Doppelklick geöffnet habe. Habe dann das Skript geöffnet, indem ich es auf das Icon des Skripteditors gezogen habe, und da lief das Skript problemlos ab. Das war gestern.
Heute war es dem Skript zunächst egal, wie ich es öffnete, es stieg immer aus.
Dann gab ich ihm eine kleine Musterdatei zu futtern, damit lief es, ab da lief es auch mit der 12-MB-Datei.

Nun soll auch eine 31-MB-Text-Datei verarbeitet werden. Nach wenigen Sekunden kommt die Meldung "AppleScript Fehler, Kein Speicher mehr verfügbar." Dabei habe ich alles, was ich so an offenen Programmen fand, geschlossen.

Jetzt bin ich mit meinem OSX- und AS-Latein am Ende. (Außer, dass Dateien ab einer bestimmten Größe möglicherweise in Häppchen verarbeitet werden könnten; aber wie?)

Hier das Skript:
-------------------

set folderPath to "Macintosh HD:Usersnder:Documents:1SatzG5:"
set importFolder to folderPath & "1 Eingang:"
set impDataFiles to {"10 Original.13", "10.13", "10.14", "10.15"}
set DataFiles4DB to {"Ori4DB.txt", "Fremd14DB.txt", "Fremd24DB.txt", "Fremd34DB.txt"}
set Feldnamen to {"OriArt DSR LfdNr SortNr Rest", "FremdArt DSR LfdNr SortNr Rest"}

set protokoll to ((current date) as string) & return & "Eingangsdaten" & return

on writeFile(tmpFilePath, allText)
 try
  open for access file tmpFilePath with write permission
  set eof of file tmpFilePath to 0
  write allText to file tmpFilePath
  close access file tmpFilePath
 on error
  try
   close access file tmpFilePath
  end try
 end try
end writeFile

repeat with i from 1 to count of impDataFiles
 set tmpFilePath to importFolder & item i of impDataFiles
 
 set tmpRef to open for access tmpFilePath
 set allText to read tmpRef as text
 close access tmpRef
 
 set cntPara to (count of paragraphs of allText) - 1
 set protokoll to protokoll & item i of impDataFiles & " enthält " & cntPara & " Zeilen." & return
 
 
 set allText to (change (ASCII character 10) into "" in allText)
 set allText to (change ¬
  "(^.{22})(.{12})(.{5})(.{3})(.{9})(.{5})(.)" into ¬
  "\\1§\\t\\2\\t\\3\\t\\4\\t$\\5\\t$\\6\\t\\7" in allText with regexp)
 set allText to (change "[ ]*§" into "" in allText with regexp)
 set allText to (change "[$][0]*" into "" in allText with regexp)
 if i = 1 then
  set allText to item i of Feldnamen & return & allText
 else
  set allText to item 2 of Feldnamen & return & allText
 end if
 set allText to (change "\" " into "◊ " in allText)
 
 set tmpFilePath to importFolder & item i of DataFiles4DB as text
 
 my writeFile(tmpFilePath, allText)
 
end repeat

set tmpFilePath to folderPath & "Testprotokoll"
set protokoll to protokoll & return & ((current date) as string) & return
set allText to protokoll
my writeFile(tmpFilePath, allText)

beep
tell application "Finder" to display dialog "Fertig." buttons {"OK"} default button 1
protokoll

---------------------

Ach ja, für Verbesserungsvorschläge zu diesem Skript bin ich dankbar, besonders, wenn es um etwas geht, das unter OSX besser etwas anders abgehandelt wird als unter OS9.

Gruß
Goar
X

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Hans Haesler
  
Beiträge gesamt: 5826

14. Apr 2005, 11:22
Beitrag # 2 von 7
Beitrag ID: #419504
Bewertung:
(1282 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Goar,

welcome back! :-))

Es ist kaum möglich, die Voraussetzungen zu rekonstruieren. Deshalb meine Frage: Ist es möglich,
dass Du mir die Textdateien senden kannst? Oder sind die Daten vertraulich?

Ich nehme an, dass diese Brocken auch gestufft für eine Sendung per Mail zu schwer sein würden.
Eine Lösung: Ich sende Dir die notwendigen Angaben, damit Du mir die Dateien per FTP übermitteln
kannst. Okay?

Gruss, Hans


als Antwort auf: [#419503]

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Goar
Beiträge gesamt: 395

14. Apr 2005, 13:53
Beitrag # 3 von 7
Beitrag ID: #419505
Bewertung:
(1282 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Hans,

natürlich nehme ich Deinen Vorschlag gerne an.
Schickst Du mir die Login-Daten?

Gruß
Goar


als Antwort auf: [#419503]

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Goar
Beiträge gesamt: 395

14. Apr 2005, 14:37
Beitrag # 4 von 7
Beitrag ID: #419506
Bewertung:
(1282 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Tja, Hans,

beim Zusammenstellen der Daten stelle ich fest, dass das Skript über 31 MB groß ist.

Jetzt bin ich mit dem Skripteditor unter OSX nicht so vertraut, habe aber schon einmal festgestellt, dass das Event-Protokoll alle Events protokolliert, auch wenn es nicht aufgeklappt ist.

Das Event-Protokoll ist jetzt vermutlich voller Datenmüll.
Das Skript lässt sich nicht mehr öffnen.
Ich werde es jetzt rekonstruieren und dann den Ablauf testen.

Wie kann ich die Speicherung der Daten im Event-Protokoll verhindern?

Gruß
Goar


als Antwort auf: [#419503]

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Hans Haesler
  
Beiträge gesamt: 5826

14. Apr 2005, 15:49
Beitrag # 5 von 7
Beitrag ID: #419507
Bewertung:
(1282 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Goar,

auch unter Mac OS X speichert das Eventprotokoll den Ablauf nur, wenn das Fenster geöffnet ist.
Doch dieses Speichern geschieht nicht im Script. Der "Beweis": Wenn das Script geschlossen wird,
kann man im Eventprotokoll immer noch die verschiedenen Einträge ansehen.

Wenn nach der Ausführung ein Script viel schwerer ist, als zu Beginn, liegt das an Variablen,
welche Werte wie Bildinhalte oder umfangreiche Texte enthalten. Damit das Script wieder
zur alten Schlankheit zurückfindet, muss man am Script-Ende Befehle einsetzen, welche
die Variablen wieder "leeren", z.B.:
Code
[b]set bigText [b]to "" 

Gruss, Hans


als Antwort auf: [#419503]

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Hans Haesler
  
Beiträge gesamt: 5826

14. Apr 2005, 16:40
Beitrag # 6 von 7
Beitrag ID: #419508
Bewertung:
(1282 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Goar,

ich habe nur einen einzigen Verbesserungsvorschlag (nebst dem oben erwähnten):
Statt den ganzen Pfad hardgecodet im Script einzutragen, kann man es so lösen:
Code
[b]set folderPath [b]to (path to "cusr" as Unicode text) & "Documents:1SatzG5:Huxaria:" 

"cusr" = Kürzel für 'current user'.

Der Vorteil: Wenn ein anderer User eingeloggt ist, oder das Script auf einer
anderen Maschine gestartet werden soll, muss man im Code nichts ändern.

Das Speicherproblem werde ich mir heute Abend vornehmen.

Gruss, Hans


als Antwort auf: [#419503]

Skripteditor steigt aus beim Skriptablauf + Speicherproblem

Hans Haesler
  
Beiträge gesamt: 5826

15. Apr 2005, 14:18
Beitrag # 7 von 7
Beitrag ID: #419509
Bewertung:
(1282 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Goar,

also ... die Meldungen betreffend gesättigtem Speicher habe ich zuverlässig reproduzieren
können. Und auch die 31-MB-Grösse des Scripts. Letzteres Problem tritt mit dem untenstehenden
Script nicht mehr auf, weil die beiden Befehle 'set allText to ""' und 'set curParas to ""'
die Variablen leeren.

Damit beim Lesen grosser Dateien kein Überlauf entsteht, wird allgemein geraten, den Text
häppchenweise (= chunks) einzulesen. Die Datei zum Lesen öffen, nicht schliessen, sondern
laufend mit 'read for' die gewünschte Anzahl Bytes einlesen. Wenn man aber Suchen- und
Ersetzenbefehle auf den aktuellen Happen anwendet, dann ist die Möglichkeit gross, dass sich
ein Teil des Suchstrings am Ende befindet und der Rest im nächsten Chunk. So geht es also nicht.

Deshalb den ganzen Text (= 387'613 Absätze) auf einmal in eine Variable lesen. Dann mit einer
Repeatschleife eine gewisse Anzahl Absätze behandeln und das Ergebnis in die Textdatei schreiben.
Mit einer Chunk-Grösse von 10'000 Absätzen kommt aber wieder die gefürchtete Meldung. Den Wert
auf 1000 reduzieren: Jetzt klappt es!

Nach genau 6 Minuten kommt die Meldung "Fertig." Es werden also alle 0.928 Sekunden
1000 behandelte Absätze in die Datei geschrieben.

Ein weiterer Vorteil: Wenn Satimage kleinere Mengen aufs Mal bearbeiten muss, wird der Ablauf
deutlich schneller. Feststellbar mit der 12-MB-Datei, welche auch ohne den Chunks-Trick keine
Fehlermeldung verursacht.

Einige Bemerkungen: Weil die Dateien nur einmal geöffnet werden, ist es nicht notwendig, sie
vor dem Lesen zu öffnen und dann wieder zu schliessen. Der 'read'-Befehl macht dies automatisch.
Und weil es ja ein Textfile ist, muss nicht 'as text' präzisiert werden.

Der Test, welcher den Tabellenkopf zuordnet, muss vor der Absatz-Repeatschleife gemacht werden,
sonst wird diese Zeile bei jedem Umgang eingefügt.

Damit der aktuelle Text-Chunk bei jedem Schreiben angefügt wird, muss die Zeile 'set eof to 0'
entfernt und die 'write'-Zeile mit 'starting at eof' ergänzt werden. Das bedingt natürlich, dass
nach Ablauf des Scripts die Datei verschoben wird. Falls sie überschrieben werden soll, dann
könnte man einen zweiten Handler einrichten, welcher aufgerufen wird, wenn die Kopfzeile in die
Datei geschrieben werden soll.
---
set folderPath to (path to "cusr" as Unicode text) & "Documents:1SatzG5:Huxaria:"
set importFolder to folderPath & "1 Eingang:"
set impDataFiles to {"400 Original.dat", "400.031", "400.033", "400.023"}
set DataFiles4DB to {"Opti4DB.txt", "Conti4DB.txt", "Gates4DB.txt", "Ruville4DB.txt"}
set Feldnamen to {"OptiArt   DSR   GenArtNr   LKZ   LfdNr   SortNr   Rest", "FremdArt   DSR   GenArtNr   LKZ   LfdNr   SortNr   Rest"}

set aChunk to 1000

set protokoll to ((current date) as string) & return & "Eingangsdaten" & return

repeat with i from 3 to count of impDataFiles
   set tmpFilePath to importFolder & item i of impDataFiles
   set defFilePath to importFolder & item i of DataFiles4DB as string
   
   set allText to read file tmpFilePath
   
   set cntPara to (count of paragraphs of allText) - 1
   set protokoll to protokoll & item i of impDataFiles & " enthält " & cntPara & " Verknüpfungen." & return
   
   if i = 1 then
      set curHead to item i of Feldnamen & return
   else
      set curHead to item 2 of Feldnamen & return
   end if
   writeFile(defFilePath, curHead)
   
   set AppleScript's text item delimiters to {return}
   repeat with p from 1 to cntPara by aChunk
      if cntPara > aChunk then
         if p < cntPara - (cntPara mod aChunk) then
            set curParas to ((paragraphs p thru (p - 1 + aChunk) of allText) as string) & return
         else
            set curParas to ((paragraphs p thru cntPara of allText) as string) & return
         end if
      else
         set curParas to ((paragraphs p thru cntPara of allText) as string) & return
      end if
     
      if curParas is not "" then
         set curParas to (change (ASCII character 10) into "" in curParas)
         set curParas to (change &not;
            "(^.{22})(.{12})(.{5})(.{3})(.{9})(.{5})(.)" into &not;
            "\\1&sect;\\t\\2\\t\\3\\t\\4\\t$\\5\\t$\\6\\t\\7" in curParas with regexp)
         set curParas to (change "[ ]*&sect;" into "" in curParas with regexp)
         set curParas to (change "[$][0]*" into "" in curParas with regexp)
         set curParas to (change "\"   " into "?   " in curParas)
         writeFile(defFilePath, curParas)
      end if
   end repeat
   set AppleScript's text item delimiters to {""}
   set allText to ""
   set curParas to ""
end repeat

set defFilePath to folderPath & "Testprotokoll"
set protokoll to protokoll & return & ((current date) as string) & return
set allText to protokoll
writeFile(defFilePath, allText)

on writeFile(defFilePath, allText)
   try
      open for access file defFilePath with write permission
      write allText to file defFilePath starting at eof
      close access file defFilePath
   on error
      try
         close access file defFilePath
      end try
   end try
end writeFile

beep
tell application "Finder" to display dialog "Fertig." buttons {"OK"} default button 1
protokoll

---
Okay ... ich nehme an, dass es mit Perl einfacher und schneller wäre. Doch das wird die nächste Etappe sein.

Gruss, Hans


als Antwort auf: [#419503]
X