Files
flowframes/Flowframes/Os/Python.cs

203 lines
7.2 KiB
C#

using Flowframes.Data;
using Flowframes.IO;
using Flowframes.MiscUtils;
using Flowframes.Ui;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace Flowframes.Os
{
class Python
{
static bool hasCheckedSysPy = false;
static bool sysPyInstalled = false;
public static string compactOutput;
public static async Task CheckCompression ()
{
if (Implementations.DisablePython || !HasEmbeddedPyFolder() || (Config.Get(Config.Key.compressedPyVersion) == Updater.GetInstalledVer().ToString()))
return;
Program.mainForm.SetWorking(true, false);
Stopwatch sw = new Stopwatch();
sw.Restart();
try
{
bool shownPatienceMsg = false;
Logger.Log("Compressing python runtime. This only needs to be done once.");
compactOutput = "";
Process compact = OsUtils.NewProcess(true);
compact.StartInfo.Arguments = $"/C compact /C /S:{GetPyFolder().Wrap()} /EXE:LZX";
compact.OutputDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
compact.ErrorDataReceived += new DataReceivedEventHandler(CompactOutputHandler);
compact.Start();
compact.BeginOutputReadLine();
compact.BeginErrorReadLine();
while (!compact.HasExited)
{
await Task.Delay(500);
if (sw.ElapsedMilliseconds > 10000)
{
Logger.Log($"This can take up to a few minutes, but only needs to be done once. (Elapsed: {FormatUtils.Time(sw.Elapsed)})", false, shownPatienceMsg);
shownPatienceMsg = true;
await Task.Delay(500);
}
}
Config.Set("compressedPyVersion", Updater.GetInstalledVer().ToString());
Logger.Log("Done compressing python runtime.");
Logger.WriteToFile(compactOutput, true, "compact");
}
catch { }
Program.mainForm.SetWorking(false);
}
static void CompactOutputHandler (object sendingProcess, DataReceivedEventArgs outLine)
{
if (outLine == null || outLine.Data == null)
return;
compactOutput = $"{compactOutput}{outLine.Data}\n";
}
public static string GetPyCmd (bool unbufferedStdOut = true, bool quiet = false)
{
if (HasEmbeddedPyFolder())
{
Logger.Log("Using embedded Python runtime.");
return Path.Combine(GetPyFolder(), "python.exe").Wrap() + (unbufferedStdOut ? " -u " : "");
}
else
{
if (IsSysPyInstalled())
{
return "python" + (unbufferedStdOut ? " -u " : "");
}
else
{
if (!quiet)
{
UiUtils.ShowMessageBox("Neither the Flowframes Python Runtime nor System Python installation could be found!\nEither redownload Flowframes with the embedded Python runtime enabled or install Python/Pytorch yourself.");
Interpolate.Cancel("Neither the Flowframes Python Runtime nor System Python installation could be found!");
}
}
}
return "";
}
public static bool HasEmbeddedPyFolder ()
{
return (Directory.Exists(GetPyFolder()) && IoUtils.GetDirSize(GetPyFolder(), false) > 1024 * 1024 * 5);
}
public static string GetPyFolder ()
{
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-amp")))
return Path.Combine(Paths.GetPkgPath(), "py-amp");
if (Directory.Exists(Path.Combine(Paths.GetPkgPath(), "py-tu")))
return Path.Combine(Paths.GetPkgPath(), "py-tu");
return "";
}
private static bool? pytorchReadyCached = null;
public static bool IsPytorchReady (bool clearCachedValue = false)
{
if (clearCachedValue)
pytorchReadyCached = null;
if (pytorchReadyCached != null)
return (bool)pytorchReadyCached;
bool pytorchReady = false;
bool hasPyFolder = HasEmbeddedPyFolder();
string torchVer = GetPytorchVer();
pytorchReady = hasPyFolder || (!string.IsNullOrWhiteSpace(torchVer) && torchVer.Length <= 35 && !torchVer.Contains("ModuleNotFoundError"));
pytorchReadyCached = pytorchReady;
return pytorchReady;
}
static string GetPytorchVer()
{
if(Implementations.DisablePython)
return "";
try
{
Process py = OsUtils.NewProcess(true);
py.StartInfo.Arguments = "\"/C\" " + GetPyCmd(true, true) + " -c \"import torch; print(torch.__version__)\"";
Logger.Log($"[DepCheck] CMD: {py.StartInfo.Arguments}", true);
py.Start();
py.WaitForExit();
string output = py.StandardOutput.ReadToEnd();
string err = py.StandardError.ReadToEnd();
if (!string.IsNullOrWhiteSpace(err)) output += "\n" + err;
Logger.Log("[DepCheck] Pytorch Check Output: " + output.Trim(), true);
return output;
}
catch
{
return "";
}
}
public static bool IsSysPyInstalled ()
{
if (hasCheckedSysPy)
return sysPyInstalled;
bool isInstalled = false;
Logger.Log("Checking if system Python is available...", true);
string sysPyVer = GetSysPyVersion();
if (!string.IsNullOrWhiteSpace(sysPyVer) && !sysPyVer.Lower().Contains("not found") && sysPyVer.Length <= 35)
{
isInstalled = true;
Logger.Log("Using Python installation: " + sysPyVer, true);
}
hasCheckedSysPy = true;
sysPyInstalled = isInstalled;
return sysPyInstalled;
}
static string GetSysPyVersion()
{
string pythonOut = GetSysPythonOutput();
Logger.Log("[DepCheck] System Python Check Output: " + pythonOut.Trim(), true);
try
{
string ver = pythonOut.Split('(')[0].Trim();
Logger.Log("[DepCheck] Sys Python Ver: " + ver, true);
return ver;
}
catch
{
return "";
}
}
static string GetSysPythonOutput()
{
Process py = OsUtils.NewProcess(true);
py.StartInfo.Arguments = "/C python -V";
Logger.Log("[DepCheck] CMD: " + py.StartInfo.Arguments, true);
py.Start();
py.WaitForExit();
string output = py.StandardOutput.ReadToEnd();
string err = py.StandardError.ReadToEnd();
return output + "\n" + err;
}
}
}