Datei in Integer konvertieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Sonntag 27. Juli 2008, 15:57

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()
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Sonntag 27. Juli 2008, 16:24

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.
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Sonntag 27. Juli 2008, 16:38

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.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Sonntag 27. Juli 2008, 16:42

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)
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Sonntag 27. Juli 2008, 16:47

@audax das wird schon in der 2ten Zeile scheitern ;)

Code: Alles auswählen

from __future__ import with_statement
OverNord
User
Beiträge: 72
Registriert: Donnerstag 24. Januar 2008, 11:59
Kontaktdaten:

Sonntag 27. Juli 2008, 16:58

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')
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Sonntag 27. Juli 2008, 16:58

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"
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Sonntag 27. Juli 2008, 17:08

@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
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Sonntag 27. Juli 2008, 17:13

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
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Sonntag 27. Juli 2008, 17:22

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.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Sonntag 27. Juli 2008, 17:27

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
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Sonntag 27. Juli 2008, 18:01

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)
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Sonntag 27. Juli 2008, 18:19

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:
Chris82
User
Beiträge: 21
Registriert: Sonntag 13. Juli 2008, 17:06

Montag 28. Juli 2008, 14:37

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?
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Montag 28. Juli 2008, 14:48

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 ...
Zuletzt geändert von Nocta am Montag 28. Juli 2008, 14:51, insgesamt 2-mal geändert.
Antworten