Seite 1 von 1

Datei in Integer konvertieren

Verfasst: Sonntag 27. Juli 2008, 15:57
von Chris82
Hallo,

Ich habe ein Problem mit einem Skript und rätsel wo das Problem liegt.
Ich habe ine .asc Datei, in der Integer vorkommen, die durch ein Leerzeichen getrennt sind, sieht etwa so aus.

1 0 11 4 8 5

Nun will ich, falls in der Datei Werte größer als 8 vorkommen, diese Datei in einem extra Ordner gespeichert wird.
Ich hab mir eine Funktion heraus gesucht, bei der die Strings in Integer konvertiert werden. Nun führe ich unten die If Anweisung aus.
Dateien mit Werten größer 8 werden auch in den extra Ordner gespeichert, allerdings auch Dateien wo alle Werte kleiner als 8 sind :(

Code: Alles auswählen

f = file('C:/Test/Testdatei.asc', 'rb')
inhalt = f.read()
# Konvertierung String in Integer
def convertType(inhalt):
    for func in (int):
        try:
            n = func(inhalt)
            return n
        except:
            pass
    return inhalt
f.close()
# Datei mit Integer groesser 8 speichern
if inhalt > 8:
    f_out = file('C:/Test/Speicherordner/Testdatei.asc', 'wb')
    f_out.write(inhalt)
    f_out.close()

Verfasst: Sonntag 27. Juli 2008, 16:24
von Nocta
Hm, ich würd's so machen:
das ganze File einlesen und nach " " splitten, dann die Liste mit einer for-Schleife durchgehen, bis ein int(element) > 8 gefunden wurde.
Keine Ahnung, was genau du in deinem Script machst, rufst du die Funktion zB überhaupt auf?
Ich denke aber dass meine Idee bei nicht allzu großen Files gut funktionieren dürfte und auch recht einfach umzusetzen ist.

Verfasst: Sonntag 27. Juli 2008, 16:38
von DasIch
inhalt ist ein String mit dem ganzen Datei Inhalt. Dass das nicht klappen kann sollte klar sein. Deine Konvertierung da ist mehr als komisch.

Code: Alles auswählen

try:
    int("foo")
except ValueError:
    pass
Mal abgesehen davon dass du die Funktion sowieso nicht aufrufst. Alle Exceptions abzufangen ist sowieso böse.

Re: Datei in Integer konvertieren

Verfasst: Sonntag 27. Juli 2008, 16:42
von audax

Code: Alles auswählen

# Konvertierung String in Integer
def convertType(inhalt):
    for func in (int):
        try:
            n = func(inhalt)
            return n
        except:
            pass
    return inhalt
f.close()
Die Funktion ist falsch und kaputt und schlecht.
`(int)` ist kein Tupel sondern das selbe wie `int`, darüber kann man nicht iterieren, außerdem konvertiert sie nicht zwangsläufig und außerdem nutzt sie ein nacktes `except`.


so könnte man es tun:

Code: Alles auswählen

from __futute__import with_statement
import os
import shutil

files = ["test1.asc", "test2.asc"]

TARGET = 'extra'

def filter_file(filepath):
    with open(filepath, 'r') as f:
        #einlesen, an Leerzeichen aufsplitten
        content = f.read().split()
        for num in content:
            try:
                if int(num) > 8:
                    return True
            # das int(num) schlug fehl
            except ValueError:
                # also den nächsten Wert versuchen
                pass
            continue
        # kein Wert war > 8
        return False

for path in files:
    if filter_file(path):
        target = os.path.join(TARGET, path)
        print "would move %s to %s" % (path, target)
        # wenn alles klappt, das hier auskommentieren:
        #shutil.move(path, target)

Verfasst: Sonntag 27. Juli 2008, 16:47
von DasIch
@audax das wird schon in der 2ten Zeile scheitern ;)

Code: Alles auswählen

from __future__ import with_statement

Verfasst: Sonntag 27. Juli 2008, 16:58
von OverNord
Moin, bin neu hier und werde jetzt auch mal meinen Senf dazu geben:

Code: Alles auswählen

def filterFile(filename):
    f = open(filename, 'rb')
    zahlen = f.read().split(' ')
    f.close()
    f = open('test/' + filename, 'wb')
    for i in range(len(zahlen)):
        try:
            zahlen[i] = int(zahlen[i])
            if zahlen[i] > 8:
                f.write(str(zahlen[i]) + ' ')
        except ValueError:
            continue
    f.close()

filterFile('test.asc')

Verfasst: Sonntag 27. Juli 2008, 16:58
von numerix
Man braucht nicht über die Menge der Zahlen zu iterieren. :wink:

Code: Alles auswählen

>>> s = "1 3 8 7 6 4 3 3 3"
>>> if max(map(int,s.split()))>8:
...     print "speichere woanders"
... else:
...     print "speichere hier"

Verfasst: Sonntag 27. Juli 2008, 17:08
von sma
@chris82: Es reicht nicht, nur eine Funktion zu definieren... falls du es tätest, könnten dir die Fehlermeldungen vielleicht helfen, weiterzukommen. Das "b" ist in dem Fall, dass du da ja mit Textdaten und nicht mit Binärdaten hantierst, übrigens unnötig und eher verwirrend.

@DasIch: Namen lösen ja immer Assoziationen aus und ich frage mich die ganze Zeit, ob du wohl so aussiehst ;) (die blöde Bemerkung sei der Hitze geschuldet)

Ansonsten, dies wäre mein Vorschlag:

Code: Alles auswählen

if any(int(x) > 8 for x in inhalt.split()):
    "inhalt schreiben"
Stefan

Verfasst: Sonntag 27. Juli 2008, 17:13
von audax

Code: Alles auswählen

import shutil
import os
from itertools import imap

def file_filter(path):
    with open(path, 'r') as current:
        if any(imap(int, current.read().split())):
            shutil.move(path, os.path.join(extra, current))
Ich kann auch kurz, wenn ich will :p

Verfasst: Sonntag 27. Juli 2008, 17:22
von Chris82
Hallo,

Danke für die Vorschläge. Werde sie mir gleich mal alle in Ruhe anschauen.
Aber gut möglich dass meine Programmierung nicht besonders gut ist als Anfänger. Tu mich mit Python leider doch noch schwer.

Verfasst: Sonntag 27. Juli 2008, 17:27
von sma
audax hat geschrieben:Ich kann auch kurz, wenn ich will :p
Du prüfst aber nicht auf Werte größer 8 :) Da musst du noch partial und gt importieren und dann eine Funktion für den Test auf > 8 bauen...

Code: Alles auswählen

functools.partial(operator.lt, 8)
Gibt es eigentlich kein rcurry in Python? Und wo ist der Kombinator-Operator, wenn man ihn braucht, um int und obigen Ausdruck zu einer neuen Funktion zu machen?

Stefan

Verfasst: Sonntag 27. Juli 2008, 18:01
von audax
ok, diesmal aber getestet:

Code: Alles auswählen

import shutil
import os
import operator as op
import string
from functools import partial
from compose import compose
from itertools import imap, ifilter

l = ["1 2 3 4 5 6 7 8 9", "123 4 2", "1 1 1 1 2 2 3 2 1 8"]

 file_filter = compose(
                    partial(compose(any, ifilter),
                        compose(partial(op.lt, 8), int)),
                            string.split)

for p in l:
    print file_filter(p)
wobei compose:

Code: Alles auswählen

def compose(*funcs):
    def comp(f, g): 
        return lambda *args, **kwargs: f(g(*args, **kwargs))
    return reduce(comp, funcs)
Und am Python2.6 gibts endlich operator.methodcaller \o/

€dit:
Mit Methodcaller eigenbau

Code: Alles auswählen

import operator as op
from functools import partial
from compose import compose
from itertools import imap, ifilter

l = ["1 2 3 4 5 6 7 8 9", "123 4 2", "1 1 1 1 2 2 3 2 1 8"]


def methodcaller(name, *args, **kwargs):
    return compose(partial(apply, *args, **kwargs), op.attrgetter(name))

file_filter = compose(partial(compose(any, ifilter), compose(partial(op.lt, 8), int)), methodcaller('split'))

for p in l:
    print file_filter(p)

Verfasst: Sonntag 27. Juli 2008, 18:19
von DasIch
sma hat geschrieben:@DasIch: Namen lösen ja immer Assoziationen aus und ich frage mich die ganze Zeit, ob du wohl so aussiehst ;) (die blöde Bemerkung sei der Hitze geschuldet)
:lol: Nö, so seh ich nicht aus. Meine Haare sind länger :wink:

Verfasst: Montag 28. Juli 2008, 14:37
von Chris82
Mit Erweiterung von sma scheint es nach einigen Tests zu klappen.

Schaut dann so aus:

Code: Alles auswählen

f = file('C:/Test/Testdatei.asc', 'rb')
inhalt = f.read()
# Datei mit Integer groesser 8 speichern
if any(int(x) > 8 for x in inhalt.split()): 
    f_out = file('C:/Test/Speicherordner/Testdatei.asc', 'wb')
    f_out.write(inhalt)
    f_out.close()
Nur verständnishalber. Was ich nicht ganz verstehe, warum muss "x" nicht vorher definiert werden? Woher weiß Python, dass int(x) immer eine Zahl in meiner Datei ist?

Verfasst: Montag 28. Juli 2008, 14:48
von Nocta
Das ist eine Generator Expression, oder wie man die Teile nennt.
Ich geb dir mal ein einleuchtenderes Beispiel:

Code: Alles auswählen

sum(i*i for i in range(10)) 
Das summiert die Quadrate aller Zahlen von 1-10.
Weiteres dazu kannst du sicher in jedem halbwegs kompletten Python Tutorial lesen.

Edit: Sorry, das sind List Comprehensions :)
Immer diese ganzen Namen ...

Verfasst: Montag 28. Juli 2008, 14:48
von Leonidas
``x`` wird ja in Zeile 5 definiert, was du vielleicht nicht weißt ist, dass erst der ``for x in ...``-Teil ausgeführt wird und dann erst der ``int(x)``-Teil.

Verfasst: Montag 28. Juli 2008, 15:21
von Zap
@ Nocta: das ist keine List Comprehension

Unterschied:

Code: Alles auswählen

In [44]: l = [str(i) for i in xrange(10)] # <- List Comprehension

In [45]: l
Out[45]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

In [46]: g = (str(i) for i in xrange(10)) # <- Generator Expression

In [47]: g
Out[47]: <generator object at 0x00EA2788>

In [48]: g.next()
Out[48]: '0'

In [49]: g.next()
Out[49]: '1'

Verfasst: Montag 28. Juli 2008, 19:54
von Nocta
Ah okay, deshalb hatte ich solche Probleme mich zu entscheiden, was es nun ist :p
Ich hab mich echt gefragt, warum ich 2 Begiffe für eine Sache im Kopf habe.
Aber ist ja auch fast das Selbe :)

Verfasst: Montag 28. Juli 2008, 21:56
von Leonidas
Zu bemerken ist noch, dass bei Generator Expressions die runden Klammern weggelassen werden können, wenn sie als (einziges) Argument in einem Funktionsaufruf vorkommen dürfen, wohl der esthetik wegen, damit es nicht wie ``callable((GE))`` aussieht.