2016-03-09 2 views
1

На хосте, у меня есть переменная среды с цитатой знак в значении, что-то вроде:Как расширить переменную окружения в python, избегая специальных символов?

export VALUE_WITH_QUOTE_FROM_OS='quote"value' 

и когда я эхо на баш, это прекрасно

#echo $VALUE_WITH_QUOTE_FROM_OS 
quote"value 

У меня есть следующий JSON строка:

json_str = '{"key":"${VALUE_WITH_QUOTE_FROM_OS}"}' 

Тогда я хочу, чтобы расширить переменную среды внутри питона сценария перед дальнейшей обработкой, что-то вроде этого

json_str = os.path.expandvars(json_str) 
json_dict = json.loads(json_str) 

Однако это расширение будет нарушать синтаксис JSON, так как json_str стал

'{"key":"quote"value"}' (<== bad unescaped quote in the value) 

вместо

'{"key":"quote\"value"}' 

Есть в любом случае я могу сообщить os.path.expandvars() избежать двойной кавычки при расширении значения? Если нет, как мне следует расширять переменную окружения, чтобы можно было избежать двойной кавычки.

Примечание 1 Значение переменной окружения является токеном безопасности, поэтому мне нужно сохранить двойную кавычку там, где есть.

Примечание 2 Текущий интерфейс json уже определен и используется в широком смысле, как есть. Этот json_str передан мне, поэтому я должен и должен только расширять переменную среды, обозначенную $ {} в строке json, никакая другая модификация не разрешена.

Примечание 3 Этот json_str чрезвычайно велик со сложной динамической вложенной структурой и потребляется несколькими клиентами, которые не могут получить доступ к переменной среды os хоста os. Хотя я могу сначала загрузить json_str, повернуть словарь, чтобы разрешить переменную окружения, а затем сбрасывать dict обратно в json_str, а затем отправлять всем клиентам, я думаю, что он менее эффективен по сравнению с обработкой его как строки ,

Спасибо.

+0

Нужно ли вам расширить переменную окружения в строке json? Не могли бы вы сделать что-то простое: '{" key ": os.env ['VALUE_WITH_QUOTE_FROM_OS']}' – mgilson

+0

@mgilson Да, этот json_str предоставляется пользователем, поэтому я ** должен расширять ** строку json.and can not измените json_str, кроме этого. – cookieisaac

ответ

2

Я, конечно, не гарантирует, что это будет иметь портативность, что вы получите с os.path, но это должно в основном работать на системах, использующих POSIX я думаю:

import re 
import os 
import json 

regex = re.compile(r'\$(\w+|\{[^}]*\})') 
json_str = '{"key":"${FOO}"}' 
def os_expandvar(match): 
    v = match.group(1) 
    if v.startswith('{') and v.endswith('}'): 
     v = v[1:-1] 
    return json.dumps(os.environ.get(v, ''))[1:-1] 
print(regex.sub(os_expandvar, json_str)) 

Регулярное выражение (и реализация идей в общие) были заимствованы из реализации os.path.expandvars в модуле posixpath. Я устранил большую сложность, чтобы упростить ответ, но вы можете вернуть его, если найдете, что вам это нужно.

Это должно обрабатывать случаи, когда строки замены - $FOO или ${FOO}, как это типично для системы posix.


Есть другие варианты здесь тоже ... На примере вы дали, вы можете декодировать JSon первый, а затем развернуть все значения.В зависимости от формата JSON, вы, возможно, потребуется рекурсивную функцию, чтобы получить работу:

# untested 
def json_expandvars(o): 
    if isinstance(o, dict): 
     return {json_expandvars(k): json_expandvars(v) for k, v in o.items()} 
    elif isinstance(o, list): 
     return [json_expandvars(v) for v in o] 
    elif isinstance(o, basestring): 
     return os.path.expandvars(o) 
    else: 
     return o 

json_dict = json_expandvars(json.loads(json_str)) 
+0

благодарит за ответ! Думаю, иногда мне приходится изобретать колесо, чтобы настроить его. – cookieisaac

0

Там нет никакого способа для os.path.expandvars знать, что результат должен быть правильной строкой JSON, с цитаты убежали.

Вместо этого разверните переменную окружения после, вы расшифровываете JSON в словаре.

json_dict = json.loads(json_str); 
json_dict['key'] = os.path.expandvars(json_dict['key']); 
+0

Это определенно возможность, но этот json_str чрезвычайно велик с очень сложным неограниченным уровнем вложенности (обычно 6-7 слоев, но нет жесткого кодированного предела). Это json_str разделяется множеством клиентов, каждый из которых заботится только о своей собственной части и точно знает, как ее интерпретировать. Поэтому в настоящее время я хочу остаться с этим дизайном и только заполнять переменные среды в процессе обработки строк для json_str, а затем отправлять его по-прежнему как строку всем клиентам, которые точно знают, как обрабатывать свою часть. – cookieisaac

+0

Я не думаю, что есть какой-либо надежный способ сделать это, другой, который пишет вашу собственную версию 'expandvars', которая ускользает от кавычек, найденных в значениях. – Barmar

+0

Я уверен, что 'json_dict.key' поднимет' AttributeError' здесь. Я обнаружил, что делаю эту ошибку, когда я слишком много работал в Javascript ... – mgilson