2011-09-13 28 views
4

在我的應用程序中,我生成了許多值(三列,類型爲int,str和datetime,請參見下面的示例),並將這些值存儲在平面文件中逗號分隔的字符串。此外,我存儲一個包含值的類型的文件(見下文)。現在,如何使用這些信息將我的值從平面文件轉換爲Python中正確的數據類型?是可能的還是我需要做一些其他的東西?使用類型()信息來將值存儲爲字符串

數據文件:

#id,value,date 
1,a,2011-09-13 15:00:00 
2,b,2011-09-13 15:10:00 
3,c,2011-09-13 15:20:00 
4,d,2011-09-13 15:30:00 

類型的文件:

id,<type 'int'> 
value,<type 'str'> 
date,<type 'datetime.datetime'> 

回答

2

據我所知,你已經解析了文件,你現在只需要得到正確的類型。我們假設id_,type_value是三個包含文件中值的字符串。 (請注意,type_應該包含'int' —例如—,不'<type 'int'>'

def convert(value, type_): 
    import importlib 
    try: 
     # Check if it's a builtin type 
     module = importlib.import_module('__builtin__') 
     cls = getattr(module, type_) 
    except AttributeError: 
     # if not, separate module and class 
     module, type_ = type_.rsplit(".", 1) 
     module = importlib.import_module(module) 
     cls = getattr(module, type_) 
    return cls(value) 

然後你可以使用它像..:

value = convert("5", "int") 

不幸的是,日期時間,雖然這並不工作,因爲它不能只需通過其字符串表示初始化即可

+1

雖然這**確實**正確地回答了這個問題,這是一個非常糟糕的方法。它有許多限制。例如,它僅限於默認的單參數轉換。例如,更改日期時間格式會導致使用可以應用於輸入的格式字符串創建閉包。這很快就會變成相當複雜的代碼,這樣即使有更簡單的選擇,getattr()和cls()也可以被強制使用。 –

+1

「type」不應​​該被稱爲 – dugres

+0

順便說一下,指定從類型(a)獲得'int'而不是(假設a是一個int類型的變量)可能會很有用, (一個名字__。但是,對於類型如,它將返回'float64'而不是'numpy.float64'。因此,根據情況,你也可以使用str(type(anObject))。split(「'」)[1]。 –

1

遵循以下步驟:

  1. 逐行讀取文件中的行,每行執行以下步驟
  2. 拆分使用split(),作爲分隔符。
  3. 將列表的第一個元素(來自第2步)作爲int進行投射。將第二個元素保留爲字符串。解析第三個值(e.g. using slices)並使相同的對象成爲datetime
+0

嗨,閱讀,分裂等完成。我試圖實現一個泛型類型轉換,使用類型文件中的信息。一般來說,我不知道列的類型是什麼,這是類型文件在運行時必須告訴我的! – aweis

+0

Ohk!然後你只需要解析類型文件並將其存儲在某個數據結構中,以便獲得文件的結構。之後,您可以根據需要解析數據文件(但我認爲您需要爲'datetime'類型做些事情)。另外,泛型類型轉換意味着內置類型還是任何用戶定義類型?如果用戶定義的類型也需要支持,那麼編程就會非常糟糕。 :) – c0da

+0

是的,我已經這樣做了,但最大的問題仍然是,我如何獲得datetime.datetime對象從我的字符串'2011-09-13 15:00:00'在運行時(這些類型也可以是小數,浮點數等)我不能只使用簡單的字符串匹配例如:tmp_type =='float':return float(val) – aweis

1

我不得不面對類似的情況在最近的一個項目中,必須轉換很多領域。我使用了元組列表,其中元組的一個元素是要使用的轉換函數。有時候是intfloat;有時候是簡單的lambda;有時它是其他地方定義的函數的名稱。

+0

請參閱OP的評論給你的答案。 OP已經完成了拆分並需要轉換數據。我的回答說明對於簡單的事情,你可以使用'int'等。對於'datetime'這樣複雜的東西,你需要一個函數。使用這樣的字段列表可讓您以結構化的方式執行此操作。 –

+0

好吧,重新閱讀它,它似乎確定... :)對不起,以前的倒票... – c0da

+0

我有我的想法轉換功能,但我想有一個更通用的方法。我正在考慮一種'序列化'的方法,如果它可能在Python中! – aweis

0

而不是有一個單獨的「類型」的文件,把你的元組列表(id, value, date)和只是pickle它。

或者您必須解決將字符串到類型轉換器存儲爲文本(在您的「類型」文件中)的問題,這可能是一個有趣的問題,但如果您只是試圖完成任務,與picklecPickle

0

首先,您不能編寫一個神奇地處理任何事情的「通用」或「智能」轉換。其次,試圖在代碼之外的任何其他任何事情中總結一個字符串到數據的轉換似乎永遠不會奏效。因此,不要編寫名稱轉換的字符串,只需編寫轉換即可。

最後,試圖用特定於領域的語言編寫配置文件是愚蠢的。只需編寫Python代碼。這並不比試圖解析某個配置文件複雜得多。

是可能的還是我需要做一些其他的東西?

不要浪費時間去嘗試創建一個不僅僅是Python的「類型文件」。它沒有幫助。將轉換寫爲Python函數更簡單。您可以將該功能導入爲您的「類型文件」。

import datetime 

def convert(row): 
    return dict(
     id= int(row['id']), 
     value= str(row['value']), 
     date= datetime.datetime.strptime(row['date],"%Y-%m-%d %H:%M:%S"), 
    ) 

這就是你在「文件類型」

現在你可以閱讀(過程)你的輸入這樣有。

from type_file import convert 
import csv 

with open("date", "rb") as source: 
    rdr= csv.DictReader(source) 
    for row in rdr: 
     useful_row= convert(row) 

在許多情況下,我不知道列數或運行

之前的數據類型這意味着你註定。

您必須具有文件內容的實際定義,否則無法進行任何處理。

"id","value","other value" 
1,23507,3 

你不知道「23507」應該是一個整數,字符串,郵政編碼,或浮點(其中省略了週期),持續時間(以天或秒)或一些其他更復雜的事情。你不能指望,也不能猜測。

獲得定義後,需要根據實際定義編寫顯式轉換函數。

寫完轉換之後,您需要(a)用一個簡單的單元測試測試轉換,並(b)測試數據以確保其真正轉換。

然後您可以處理該文件。

+0

所以從我聽到的是,沒有'智能'的方式根據Python提供的類型信息將字符串值轉換爲特定類型。我需要創建一個轉換功能我的自我?請注意,我的數據文件是自動生成的,在很多情況下,我不知道運行前的列數或數據類型! – aweis

+0

@aweis:「沒有'聰明'的方式將字符串值轉換爲特定類型」? Python代碼是將字符串轉換爲特定類型的* smart *方式。有太多的變化和選擇以及可能的變化,您必須每次寫**顯式轉換代碼。沒有真正的選擇。 Python代碼就是你如何寫出「聰明」的東西。每種新的文件格式都可能意味着新的轉換。有人必須編寫「類型文件」。不管你認爲你的代碼如何「聰明」。 –

1

您的類型文件可以更簡單:

id=int 
value=str 
date=datetime.datetime 

然後在你的主程序可以

import datetime 

def convert_datetime(text): 
    return datetime.datetime.strptime(text, "%Y-%m-%d %H:%M:%S") 

data_types = {'int':int, 'str':str, 'datetime.datetime':convert_datetime} 
fields = {} 

for line in open('example_types.txt').readlines(): 
    key, val = line.strip().split('=') 
    fields[key] = val 

data_file = open('actual_data.txt') 
field_info = data_file.readline().strip('#\n ').split(',') 
values = [] #store it all here for now 

for line in data_file.readlines(): 
    row = [] 
    for i, element in enumerate(line.strip().split(',')): 
     element_type = fields[field_info[i]] # will get 'int', 'str', or 'datetime' 
     convert = data_types[element_type] 
     row.append(convert(element)) 
    values.append(row) 

# to show it working... 
for row in values: 
    print row 
0

你可能想看看xlrd模塊。如果您可以將數據加載到excel中,並且知道每個列與哪種類型相關聯,那麼當您讀取excel文件時,xlrd會爲您提供類型。當然,如果數據以csv的形式提供給你,那麼有人需要進入excel文件並手動更改列類型。

不知道這會讓你一路走到你想去的地方,但它可能有幫助

相關問題