I wrote a simple extension for vscode, which registers a command, namely comandName.
In my package.json file I have:
"activationEvents": [
"onLanguage:python",
"onCommand:commandName"
]
I meant to execute this command only for Python. To my knowledge, however, the activationEvents in my package.json means that the command would be activated when a Python file is opened or the command is executed. But the command can be executed within any language. I searched the documentation but found no way to execute the command for certain languages.
Is there any way to achieve this target?
I'm afraid this is impossible for now. However you can work around this to avoid any side effects on other files.
If you bind this command to some key combination or to context menu you can use when clause to limit the command to specific types of files.
It will still allow to execute the command from command palette though. To work around this you can just ignore it when being in file other than Python:
vsc.commands.registerTextEditorCommand('testCommand', editor => {
if (editor.document.languageId !== 'python') {
return
}
// command logic
}))
Notice I used registerTextEditorCommand instead of regular command. The difference is that this one requires user to be in text editor context to work which is what you probabl
Related
I am fairly new to Python and .NET in general, but decided to ask more competent people, since I have been struggling with the issue of executing python script from Windows Forms.
The basic idea of my project is a desktop applicaton and the overall logic would be to read from a couple of selected check boxes, pass the values of those selections to my python script, from there I generate an excell table based on those results, and display this table back into the Windows Forms application.
Creating the table and managing to display it in the Desktop App is already done, but I am having serious issues with the communication between the two platforms, when it came to executing the script itself.
I have tried using IronPython and it worked perfectly, untill the fact that I found that Iron Python does not support CPython packages, like Pandas, which is build on numpy, and numpy apparantly is one of those packages. I looked over a lot of articles about this issue and the answers did not seem promising and most of the suggestions were to use pythonnet.
I tried to implement pythonnet, following numerous articles and all I managed to do, besides creating a bigger mess, is nothing as a result.
Finally, I decided to use C# Process class, but did not succeed also.
Would appreciate if there are any comments and suggestions on how to remedy this issue.
Python version: 3.7
Windows 10 (64 bit)
.NET Framework 4.7.2
Here is some of my code attempts in Windows Forms:
Implementation with the usage of the Process Class
Issue here is that I am not able to run this script due to the error messages that it cannot find the packages for the python script
var processStartInfo = new ProcessStartInfo
{
Arguments = "C:\\Users\\Dobromir\\PycharmProjects\\pythonProject\\main.py",
FileName = "C:\\Python27\\python.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
Process.Start(processStartInfo);
Implementation using IronPython (which was working before the usage of pandas package)
Issue here is the CPython packages limitation and errors.
For IronPython I had to downgrade to Python 2.7 in order to work with it. For the rest of the examples I am using Python 3.7
ScriptEngine pythonEngine = Python.CreateEngine();
var searchPaths = pythonEngine.GetSearchPaths();
searchPaths.Add(#"C:\Python27\Lib");
searchPaths.Add(#"C:\Users\Dobromir\PycharmProjects\pythonProject\venv\Lib\site-packages");
pythonEngine.SetSearchPaths(searchPaths);
List<String> argv = new List<String>();
argv.Add("Some Value1");
argv.Add("Some Value2");
ScriptSource pythonScript = pythonEngine.CreateScriptSourceFromFile("C:\\Users\\Dobromir\\PycharmProjects\\pythonProject\\main.py");
pythonEngine.GetSysModule().SetVariable("argv", argv);
pythonEngine.SetSearchPaths(searchPaths);
ScriptScope scope = pythonEngine.CreateScope();
pythonScript.Execute(scope);
Implementation of pythonnet
The issue that I got here is on the line using Py.GIL(). I believe it is having trouble finding the python files, and also tried giving the python37.dll in the variable pathToPython.
I received the error that Python.Runtime, Version=2.5.2.0, Culture=neutral....missmatch"
string pathToPython = #"C:\Users\Dobromir\AppData\Local\Programs\Python\Python37";
string path = pathToPython + "; " + Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Machine);
Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("PYTHONHOME", pathToPython, EnvironmentVariableTarget.Process);
Console.WriteLine(path);
var lib = new[]
{
#"C:\\Users\\Dobromir\\PycharmProjects\\App37\\main.py",
Path.Combine(pathToPython, "Lib"),
Path.Combine(pathToPython, "DLLs")
};
string paths = string.Join("; ", lib);
Environment.SetEnvironmentVariable("PYTHONPATH", paths, EnvironmentVariableTarget.Process);
using (Py.GIL()) //Initialize the Python engine and acquire the interpreter lock
{
try
{
Console.WriteLine("I am working");
}
catch (PythonException error)
{
Console.WriteLine("Error occured: ", error.Message);
}
}
I Also tried creating a bash script to execute the python script and got the no module found error as well
I know that these are not the best implementations out there, but do the job.
My question is if someone has any idea on how to make this simple operation work I would be very grateful, thank you for your time and understanding
P.S - Apologies for the long post, wanted to write what I have tried before asking for help, but if someone is more interested I will provide additional information.
I did a project like this recently; a couple of things I would suggest to make it easy:
Confirm that the instance of python set in your env variables (WIN+R, sysdm.cpl, Advanced, env variables) is that of the instance of python you wish to use (do this for your python search path too!)
Remove any lines attempting to set these in code; and instead handle errors if they are not found
Then, when you call you script from within your program; it only needs to look like this:
var processStartInfo = new ProcessStartInfo
{
Arguments = "main.py",
FileName = "Python",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
Process.Start(processStartInfo);
After some struggle, I found a solution to fit my needs.
Firstly, I completely removed python 2.7 and installed back 3.10.
I tried running the script file inside the shell command line and got the same error that the modules could not be found. What I did is try to import these modules and it gave an error, specifically for bs4 that I am using packages for python 2.x instead of 3.x packages.
After futher investigation I discovered that the packages that I have for my script are treated as "local" packages, meaning I installed them from the IDE (PyCharm) and they work for that project only I guess.
I also found that to "globally" access these packages I had to install them through the command line using the pip3 install <package_name>. After doing this the problem was gone and was left with running the script from the Windows Forms.
NOTE: I did not manage to start the script using python.exe, so I used bash script for the job.
Here is my code and I hope it helps someone down the line...
Code in C#
string myApp = string.Format("{0} {1}", #"C:\testing1.sh", "Hello");
var processStartInfo = new ProcessStartInfo
{
Arguments = myApp,
FileName = "C:\\Program Files\\Git\\git-bash.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = false
};
Process.Start(processStartInfo)
Code in Bash Script File
#!/bin/bash
arg1="$1"
python C:/Users/Dobromir/PycharmProjects/testing/main.py "$arg1"
Inside the Python file I am using sys.argv[] and accessing the arguments.
NOTE: Passing arguments from the bash script to the python script, in this case, you will receive 2 arguments - first one is the path to the python file and the second is the variable arg1.
Another important thing to mention is you need to have comas around the $1 - this is the property that is being send from the C# file, else it will show as empty.
Articles that were useful:
Installed BeautifulSoup but still get no module named bs4
Passing arguments to Python from Shell Script
https://unix.stackexchange.com/questions/31414/how-can-i-pass-a-command-line-argument-into-a-shell-script
https://gist.github.com/creativcoder/6df4d349447ff1416e68
Thank you to everyone who contributed and tried to help, I managed to learned new things with your suggestions!
Is there a way to configure VS Code to only execute a python script if there are no linter errors? I am using Python 3.9.0 and VS Code 1.49.0. Linter is mypy (mypy-0.790, mypy-extensions-0.4.3, typed-ast-1.4.1, typing-extensions-3.7.4.3). OS is Windows 10, version 2004.
Currently, while linter reports problems correctly (incompatible type, based on type hints, for instance), pressing F5 still runs the code (which crashes, as the linter is correct). I would like VS Code to only proceed to the "Run" step if the linter output has no errors, as the time taken to execute a script with linter errors is basically a waste of time.
How can this be configured?
First, create a new task. If you don't already have a tasks.json file in the .vscode folder (or you don't have a .vscode folder), you can press F1 and run "Tasks: Configure Task", then select "Create tasks.json file from template". Select "Others" from the list of templates. It should generate a file that looks like this:
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo Hello"
}
]
}
Change the label to "lint" (or any other label that suits your fancy), and change the command to "mypy <directories or files>". For more information on the mypy command, refer to the docs.
If you do already have a tasks.json file, just copy the part inside the tasks array into your tasks array and make the same changes.
Then, open your launch.json and add the following line into whichever configuration(s) you're using.
"preLaunchTask": "lint",
If the task fails, you'll see a dialogue box pop up saying
The preLaunchTask 'lint' terminated with exit code 1.
and asking if you want to "Debug Anyway", Show Errors", or "Abort". There'll also be a checkbox to have VS Code remember your choice in your settings (if you'd like to set this before the first time you get an error, the setting is named debug.onTaskErrors).
Additional resources:
Tasks Documentation
Debugging Documentation
Description of debug.onTaskErrors
In Maya 2018, using Python, how can you check if the attribute editor is open, and if it is not, open it. Also, can you open multiple instances of the attribute editor, preferably showing the attributes of different nodes?
I advise you to turn on "echo all command" if your looking to some code.
Opening the Attribute Editor will give you in echo :
attributeEditorVisibilityStateChange(`workspaceControl -q -visible AttributeEditor`, "");
In this command you can already guess that :
`workspaceControl -q -visible AttributeEditor`
it is the part to query the visibility of the attribute editor, in python a simple translation :
cmds.workspaceControl('AttributeEditor', q=1, visible=1)
Then you have this mel function :
attributeEditorVisibilityStateChange
In Mel you can use this command to find where the procedure belong :
whatIs attributeEditorVisibilityStateChange;
// Result: Mel procedure found in: D:\maya_path\scripts\startup\initAttributeEditor.mel //
Opening the file and reading the first proc, you find already : showAttributeEditor
This function is commented as obsolet and advise to use : ToggleAttributeEditor
Making a quick whatIs, i find out it was a runtime command (so it should be use straight away):
cmds.ToggleAttributeEditor()
You should have your answer for opening and check if the atrribute editor still exists, if the command is not the one you want because you want maybe some docking ability, there is lots more MEL to read using whatIs; and the second proc in the file.
And now that I've explained you the method to find python command, I think you can use the same technique to create a function for the "copy tab" of the attribute editor !
If you find it is to annoying (maya has sometimes lots of nested code, and it can be tidious), you can use :
import maya.mel
mel.eval('attributeEditorVisibilityStateChange(`workspaceControl -q -visible AttributeEditor`, "");')
it will execute mel code inside python. you can use python format to insert arguments...etc as it must be evaluated as a string.
I'm currently making a program (which requires some arguments) that runs on the terminal.
Now I would like to run this same program from Sublime Text, but I don't know how to pass parameters to the build before executing the program in Sublime Text.
Is there any option that I need to enable to specify the arguments?
Using Sublime Text 3 build 3035
You can create a new build system for sublime text and run your script with fixed arguments.
Create a new File in your Packages/User directory (CTRL-SHIFT-P --> "Browse Packages")
New File: Packages/User/my_build.sublime-build
with the following content:
{
"cmd": ["python", "$file", "arg1", "arg2"]
}
(replace arg1,arg2 by your arguments - you can delete them or add more if you want)
Now restart sublime text and select your build system in the Menu: Tools --> Build System --> my_build. From now on, when you press CTRL-B your build system will be executed.
Don't forget to change it back to "Automatic" if you are working on other files or projects.
There are many options you can set in build files. Please refer to https://docs.sublimetext.io/guide/usage/build-systems.html
I find it easier to use a try catch with default arguments, Sublime's build system becomes annoying to manage. While you do fast paced dev you can just modify the arguments in the except statement.
import sys
try:
if sys.argv[1]:
Name = str(sys.argv[1])
except:
print "no argument given - using DERP"
Name = "DERP"
I am really fond of python's capability to do things like this:
if __name__ == '__main__':
#setup testing code here
#or setup a call a function with parameters and human format the output
#etc...
This is nice because I can treat a Python script file as something that can be called from the command line but it remains available for me to import its functions and classes into a separate python script file easily without triggering the default "run from the command line behavior".
Does Powershell have a similar facility that I could exploit? And if it doesn't how should I be organizing my library of function files so that i can easily execute some of them while I am developing them?
$MyInvocation.Invocation has information about how the script was started.
If ($MyInvocation.InvocationName -eq '&') {
"Called using operator: '$($MyInvocation.InvocationName)'"
} ElseIf ($MyInvocation.InvocationName -eq '.') {
"Dot sourced: '$($MyInvocation.InvocationName)'"
} ElseIf ((Resolve-Path -Path $MyInvocation.InvocationName).ProviderPath -eq $MyInvocation.MyCommand.Path) {
"Called using path: '$($MyInvocation.InvocationName)'"
}
$MyInvocation has lots of information about the current context, and those of callers. Maybe this could be used to detect if a script is being dot-sourced (i.e. imported) or executed as a script.
A script can act like a function: use param as first non-common/whitespace in the file to defined parameters. It is not clear (one would need to try different combinations) what happens if you dot-source a script that starts param...
Modules can directly execute code as well as export functions, variables, ... and can take parameters. Maybe $MyInvocation in a module would allow the two cases to be detected.
EDIT: Additional:
$MyInvocation.Line contains the command line used to execute the current script or function. Its Line property has the scrip text used for the execution, when dot-sourcing this will start with "." but not if run as a script (obviously a case to use a regex match to allow for variable whitespace around the period).
In a script run as a function
As of now I see 2 options that work
if ($MyInvocation.InvocationName -ne '.') {#do main stuff}
and
if ($MyInvocation.CommandOrigin -eq 'Runspace') {#do main stuff}
Disclaimer: This is only tested on Powershell Core on Linux. It may not work the same for Windows. If anyone tries it on Windows I would appreciate if you could verify in the comments.
function IsMain() {
(Get-Variable MyInvocation -Scope Local).Value.PSCommandPath -Eq (Get-Variable MyInvocation -Scope Global).Value.InvocationName
}
Demonstrated with a gist