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

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

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: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

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

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: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@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:

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

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

@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

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

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

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

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: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

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

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

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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

``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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

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

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 :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten