See More

using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using NLog; using System; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MatplotlibCS { ///

/// Обёртка над питоновским скриптом построения графиков /// // ReSharper disable once InconsistentNaming public class MatplotlibCS { #region Fields private readonly ILogger _log; /// /// Пусть к интерпрететору питона /// private readonly string _pythonExePath; /// /// Путь к скрипту dasPlot.py /// private readonly string _dasPlotPyPath; /// /// Path to build_figure.py /// private readonly string _buildFigurePyPath; /// /// Путь директории, в которой хранятся временные json-файлы, через которые передаются параметры задачи /// private readonly string _jsonTempPath; /// /// Python web service URL /// private readonly string _serviceUrlCheckAliveMethod = "http://127.0.0.1:57123/"; /// /// Python web service URL /// private readonly string _serviceUrlPlotMethod = "http://127.0.0.1:57123/plot"; /// /// Kill web service url /// //private string _serviceUrlKillMethod = "http://127.0.0.1:57123/kill"; #endregion #region .ctor /// /// Обёртка над python скриптом, строящим matplotlib графики /// /// Путь python.exe /// Путь dasPlot.py /// Path to build_figure.py /// Опциональный путь директории, в которой хранятся временные json файлы, через которые передаются данные public MatplotlibCS(string pythonExePath, string dasPlotPyPath, string buildFigurePyPath, string jsonTempPath = "c:\\MatplotlibCS") { _pythonExePath = pythonExePath; _dasPlotPyPath = dasPlotPyPath; _buildFigurePyPath = buildFigurePyPath; _jsonTempPath = jsonTempPath; _log = LogManager.GetLogger(typeof(MatplotlibCS).Name); if (!Directory.Exists(_jsonTempPath)) Directory.CreateDirectory(_jsonTempPath); } #endregion #region Public methods public async Task BuildFigureViaFile(Figure task) { task.HealthCheck(); try { var json = BuildJson(task); var fullpath = Path.Combine(AppContext.BaseDirectory, $"matplotlib_cs.input.json"); await File.WriteAllTextAsync(fullpath, json); await RunPython(fullpath); } catch (Exception ex) { _log.Fatal($"Error while building figure: {ex.Message}\n{ex.StackTrace}"); } } /// /// Выполняет задачу построения графиков /// /// Описание задачи public async Task BuildFigure(Figure task) { task.HealthCheck(); try { await LaunchPythonWebServiceAsync(); var json = BuildJson(task); JsonConvert.DefaultSettings = (() => { var settings = new JsonSerializerSettings(); settings.Converters.Add(new StringEnumConverter { NamingStrategy = new CamelCaseNamingStrategy() }); return settings; }); using var client = new HttpClient(); var content = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json"); var response = await client.PostAsync(_serviceUrlPlotMethod, content); var responseString = await response.Content.ReadAsStringAsync(); } catch (Exception ex) { _log.Fatal($"Error while building figure: {ex.Message}\n{ex.StackTrace}"); } } #endregion #region Private methods private string BuildJson(Figure task) { if (!Path.IsPathRooted(task.FileName)) task.FileName = Path.Combine(_jsonTempPath, task.FileName); var serializer = new JsonSerializer() { StringEscapeHandling = StringEscapeHandling.EscapeHtml }; var sb = new StringBuilder(); using (var writer = new StringWriter(sb)) { serializer.Serialize(writer, task); } var json = sb.ToString(); return json; } private async Task RunPython(string inputfile) { var ps = new ProcessStartInfo { FileName = _pythonExePath, Arguments = $"{_buildFigurePyPath} {inputfile}", UseShellExecute = false, RedirectStandardOutput = true }; using Process process = Process.Start(ps); await process.WaitForExitAsync(); } /// /// Check if python web service is alive and if no, launches it /// private async Task LaunchPythonWebServiceAsync() { if (!await CheckIfWebServiceIsUpAndRunningAsync()) { var psi = new ProcessStartInfo(_pythonExePath, _dasPlotPyPath) { RedirectStandardOutput = true, RedirectStandardError = true, RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }; _log.Info($"Starting python process {_pythonExePath}, {_dasPlotPyPath}"); Process.Start(psi); // when starting python process, it's better to wait for some time to ensure, that // web service started await Task.Delay(2000); } } /// /// Check if python web service is alive /// /// true if service is up and running private async Task CheckIfWebServiceIsUpAndRunningAsync() { try { _log.Info("Check if python web-service is already running"); var client = new HttpClient(); using var response = await client.GetAsync(_serviceUrlCheckAliveMethod); _log.Info($"Service response status is {response.StatusCode}"); return (response.StatusCode == HttpStatusCode.OK); } catch (Exception) { _log.Info("Python web-service wasn't found"); //Any exception will returns false. return false; } } #endregion } }