Fix changing locale. (#5314)
* Fix changing locale. * Don't use locale guard. As number parsing is implemented in house, we don't need locale. * Update doc.
This commit is contained in:
parent
69fc8a632f
commit
088c43d666
@ -195,7 +195,9 @@ You can load it back to the model generated by same version of XGBoost by:
|
|||||||
|
|
||||||
bst.load_config(config)
|
bst.load_config(config)
|
||||||
|
|
||||||
This way users can study the internal representation more closely.
|
This way users can study the internal representation more closely. Please note that some
|
||||||
|
JSON generators make use of locale dependent floating point serialization methods, which
|
||||||
|
is not supported by XGBoost.
|
||||||
|
|
||||||
************
|
************
|
||||||
Future Plans
|
Future Plans
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
* Copyright (c) by Contributors 2019
|
* Copyright (c) by Contributors 2019
|
||||||
*/
|
*/
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <locale>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -692,47 +693,23 @@ Json JsonReader::ParseBoolean() {
|
|||||||
return Json{JsonBoolean{result}};
|
return Json{JsonBoolean{result}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is an ad-hoc solution for writing numeric value in standard way. We need to add
|
|
||||||
// a locale independent way of writing stream like `std::{from, to}_chars' from C++-17.
|
|
||||||
// FIXME(trivialfis): Remove this.
|
|
||||||
class GlobalCLocale {
|
|
||||||
std::locale ori_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GlobalCLocale() : ori_{std::locale()} {
|
|
||||||
std::string const name {"C"};
|
|
||||||
try {
|
|
||||||
std::locale::global(std::locale(name.c_str()));
|
|
||||||
} catch (std::runtime_error const& e) {
|
|
||||||
LOG(FATAL) << "Failed to set locale: " << name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~GlobalCLocale() {
|
|
||||||
std::locale::global(ori_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Json Json::Load(StringView str) {
|
Json Json::Load(StringView str) {
|
||||||
GlobalCLocale guard;
|
|
||||||
JsonReader reader(str);
|
JsonReader reader(str);
|
||||||
Json json{reader.Load()};
|
Json json{reader.Load()};
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json Json::Load(JsonReader* reader) {
|
Json Json::Load(JsonReader* reader) {
|
||||||
GlobalCLocale guard;
|
|
||||||
Json json{reader->Load()};
|
Json json{reader->Load()};
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Json::Dump(Json json, std::ostream *stream, bool pretty) {
|
void Json::Dump(Json json, std::ostream *stream, bool pretty) {
|
||||||
GlobalCLocale guard;
|
|
||||||
JsonWriter writer(stream, pretty);
|
JsonWriter writer(stream, pretty);
|
||||||
writer.Save(json);
|
writer.Save(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Json::Dump(Json json, std::string* str, bool pretty) {
|
void Json::Dump(Json json, std::string* str, bool pretty) {
|
||||||
GlobalCLocale guard;
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
JsonWriter writer(&ss, pretty);
|
JsonWriter writer(&ss, pretty);
|
||||||
writer.Save(json);
|
writer.Save(json);
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
import testing as tm
|
import testing as tm
|
||||||
import pytest
|
import pytest
|
||||||
|
import locale
|
||||||
|
|
||||||
dpath = 'demo/data/'
|
dpath = 'demo/data/'
|
||||||
dtrain = xgb.DMatrix(dpath + 'agaricus.txt.train')
|
dtrain = xgb.DMatrix(dpath + 'agaricus.txt.train')
|
||||||
@ -300,6 +301,7 @@ class TestModels(unittest.TestCase):
|
|||||||
'reg_loss_param']['scale_pos_weight']) == 0.5
|
'reg_loss_param']['scale_pos_weight']) == 0.5
|
||||||
|
|
||||||
def test_model_json_io(self):
|
def test_model_json_io(self):
|
||||||
|
loc = locale.getpreferredencoding(False)
|
||||||
model_path = 'test_model_json_io.json'
|
model_path = 'test_model_json_io.json'
|
||||||
parameters = {'tree_method': 'hist', 'booster': 'gbtree'}
|
parameters = {'tree_method': 'hist', 'booster': 'gbtree'}
|
||||||
j_model = json_model(model_path, parameters)
|
j_model = json_model(model_path, parameters)
|
||||||
@ -313,6 +315,7 @@ class TestModels(unittest.TestCase):
|
|||||||
assert isinstance(j_model['learner'], dict)
|
assert isinstance(j_model['learner'], dict)
|
||||||
|
|
||||||
os.remove(model_path)
|
os.remove(model_path)
|
||||||
|
assert locale.getpreferredencoding(False) == loc
|
||||||
|
|
||||||
@pytest.mark.skipif(**tm.no_json_schema())
|
@pytest.mark.skipif(**tm.no_json_schema())
|
||||||
def test_json_schema(self):
|
def test_json_schema(self):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user