2017-06-02 146 views
0

我有一個需要配置文件的Python測試腳本。預計配置文件將採用JSON格式。有沒有辦法確定文件是YAML格式還是JSON格式?

但是我的測試腳本的一些用戶不喜歡JSON格式,因爲它是不可讀的。

因此,我更改了我的測試腳本,以便它期望YAML格式的配置文件,然後將YAML文件轉換爲JSON文件。

我寧願加載配置文件來處理JSON和YAML的函數。如果配置文件是JSON或YAML,yaml或json模塊中是否有方法可以給我一個布爾響應?

我的解決辦法,現在是使用兩個的try/except子句:

import os 
import json 
import yaml 

# This is the configuration file - my script gets it from argparser but in 
# this example, let's just say it is some file that I don't know what the format 
# is 
config_file = "some_config_file" 

in_fh = open(config_file, "r") 

config_dict = dict() 
valid_json = True 
valid_yaml = True 

try: 
    config_dict = json.load(in_fh) 
except: 
    print "Error trying to load the config file in JSON format" 
    valid_json = False 

try: 
    config_dict = yaml.load(in_fh) 
except: 
    print "Error trying to load the config file in YAML format" 
    valid_yaml = False 

in_fh.close() 

if not valid_yaml and not valid_json: 
    print "The config file is neither JSON or YAML" 
    sys.exit(1) 

現在,有一個Python模塊我在互聯網上被稱爲isityaml可用於測試YAML發現。但我不想安裝另一個軟件包,因爲我必須在多個測試主機上安裝這個軟件包。

json和yaml模塊是否有一個方法可以讓我返回一個測試它們各自格式的布爾值?

config_file = "sample_config_file" 

# I would like some method like this 
if json.is_json(in_fh): 
    config_dict = json.load(in_fh) 
+3

YAML不是JSON的超集嗎?您應該能夠無條件地將文件作爲YAML加載。 (我不確定它是否是一個確切的超集 - 我認爲以前的版本不是。) – user2357112

+1

難道你只需要YAML文件有一個擴展名和JSON文件有不同的擴展名? – user2357112

+0

user2357112,有兩個問題。 1)某些用戶可能會在沒有.yml或.json後綴的情況下爲其配置文件命名,所以我不能通過其配置文件中的後綴 2)僅僅因爲文件具有.yml後綴並不一定意味着該文件是YAML格式。 – SQA777

回答

0

從看jsonyaml模塊的文檔,它看起來像他們沒有提供任何適當的模塊。然而,一個常見的Python成語是EAFP(「比請求更容易要求原諒」);換句話說,繼續嘗試做這個操作,並且在出現異常時處理異常。

def load_config(config_file): 
    with open(config_file, "r") as in_fh: 
     # Read the file into memory as a string so that we can try 
     # parsing it twice without seeking back to the beginning and 
     # re-reading. 
     config = in_fh.read() 

    config_dict = dict() 
    valid_json = True 
    valid_yaml = True 

    try: 
     config_dict = json.loads(config) 
    except: 
     print "Error trying to load the config file in JSON format" 
     valid_json = False 

    try: 
     config_dict = yaml.safe_load(config) 
    except: 
     print "Error trying to load the config file in YAML format" 
     valid_yaml = False 

你可以使自己的is_jsonis_yaml功能,如果你想。這將涉及兩次處理配置,但這對您的目的可能沒有問題。

def try_as(loader, s, on_error): 
    try: 
     loader(s) 
     return True 
    except on_error: 
     return False 

def is_json(s): 
    return try_as(json.loads, s, ValueError) 

def is_yaml(s): 
    return try_as(yaml.safe_load, s, yaml.scanner.ScannerError) 

最後,@ user2357112提到,"every JSON file is also a valid YAML file"(如YAML 1.2),所以你應該能夠無條件地處理一切,YAML(假設你有一個YAML 1.2兼容的解析器; Python的默認yaml模塊ISN 「T)。

+0

您的上一條語句並不適用,因爲OPs'import yaml'指PyYAML,它只支持舊的YAML 1.1規範。 – Anthon

+0

@安永 - 感謝您的糾正。 –

+0

做'try'和'except'而不指定例外是不好的做法。在JSON中遇到的異常是**'ValueError **。 yaml模塊甚至不會引發異常。 –

3

從你

import yaml 

我斷定你使用舊PyYAML。該軟件包僅支持YAML 1.1(從2005年開始),並且指定的格式不是JSON的完整超集。隨着YAML 1.2(2009年發佈),YAML格式成爲JSON的超集。

ruamel.yaml(聲明:我是該包的作者)支持YAML 1.2。因此,通過由ruamel.yaml更換PyYAML(而不是增加一個包),你可以這樣做:

import os 
from ruamel import yaml 

config_file = "some_config_file" 

with open(config_file, "r") as in_fh: 
    config_dict = yaml.safe_load(in_fh) 

和文件加載到config_dict,不關心輸入是YAML或JSON,也不需要有一個測試無論是哪種格式。

請注意,我使用safe_load()作爲在YAML文件上使用load(),您沒有100%的控制權(並且您沒有)是不安全的。 (ruamel。yaml會提醒你,PyYAML不會)。

相關問題