Why does argparse fail to recognise an argument when a Python script is called directly? - windows

I have a simple script like this (based on the docs for argparse):
def Main():
parser = argparse.ArgumentParser()
parser.add_argument("issuenumber", help="Create a local branch based on the specified issue number", type=int)
args = parser.parse_args()
if args.issuenumber:
print("Starting work on issue #"+str(args.issuenumber))
if __name__ == "__main__":
Main()
When I run it however, it never recognises the argument I'm passing it:
C:\Projects\PyTools>Gritter.py 1
usage: Gritter.py [-h] issuenumber
Gritter.py: error: the following arguments are required: issuenumber
If I call the script via a python call it works however:
C:\Projects\PyTools>python Gritter.py 1
Starting work on issue #1
If I print out sys.argv I get:
C:\Projects\PyTools>Gritter 1
['C:\\Projects\\PyTools\\Gritter.py']
C:\Projects\PyTools>Python Gritter.py 1
['Gritter.py', '1']
So I guess something is not passing on the arguments when the script is called directly. I wonder if there's anything that can be done so that the script can be called directly?

The C\ indicates you are using Windows. You have take extra effort to ensure that this 'direct call' passes arguments through to python.
Looking up windows shebang I find, from Python docs that you need to use
#!/usr/bin/python -v
to pass arguments
See https://docs.python.org/3/using/windows.html
argparse uses sys.argv. If that only has the script name then the call isn't passing arguments.

Based on mckoss` answer, I modified the following registry key:
HKEY_CLASSES_ROOT\Applications\python.exe\shell\open\command
From this:
"C:\Python34\python.exe" "%1"
To this:
"C:\Python34\python.exe" "%1" %*
And now my script works as I'd previously expected.

Related

How do I pass a custom argument to non-test module?

I am trying to set a new argument in my test suite and I would like to pass it along pytest commands (e.g. pytest --arg=foo, or pytest --arg=bar path/to/test.py::test_func). Then, those arguments must be used inside some other module. Not test one.
I tried with sys.argv as it is the easiest method and I only need one argument.
To import into Python Scripts you need to parse arguments.
#!/usr/bin/env python
import argparse
def main(def_args=sys.argv[1:]):
args = arguments(def_args)
user_name = args.user_name
....
//Rest of code
def arguments(argsval):
parser = argparse.ArgumentParser()
parser.add_argument('-un', '--user_name', type=str, required=False,
help="""Overrides user.name git config.
If not specified, the global config is used.""")
Then pass your args in your pytest file.
How to pass arguments in pytest by command line

How can I store "image lookup -v address" result inside a variable?

I am able to symbolicate symbol address through following lldb command:
image lookup --address $SYMBOL_ADDRRESS
But while writing a shell script to parse, I am not able to find a way to store the output of above command into a variable or file.
First off, if your script's job is mostly about driving lldb and you happen to know Python, you will be much happier using the lldb module in Python, where you can drive the debugger directly, than getting lldb to produce text output which you parse in the shell script.
The lldb Python module provides API's like SBTarget.ResolveSymbolContextForAddress, which runs the same lookup as image lookup --address but returns the result as a Python lldb.SBSymbolContext object, which you can either query for module/file/line etc using API's on the object. So getting bits of info out of this result will be easier with the lldd API's.
But if you have to use a shell script, then the easiest thing is probably to write the command output to a file and read that back into the shell script. lldb doesn't have generic support for tee-ing command output into a log file yet, but the lldb Python module allows you to run command-line commands and programmatically capture the output.
So you can do it easily from lldb's Python script interpreter:
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> result = lldb.SBCommandReturnObject()
>>> lldb.debugger.GetCommandInterpreter().HandleCommand("image lookup -va $pc", result)
2
>>> fh = open("/tmp/out.txt", "w")
>>> fh.write(result.GetOutput())
>>> fh.close()
>>> quit
(lldb) plat shell cat /tmp/out.txt
Address: foo[0x0000000100003f6f] (foo.__TEXT.__text + 15)
Summary: foo`main + 15 at foo.c:6:3
Module: file = "/tmp/foo", arch = "x86_64"
CompileUnit: id = {0x00000000}, file = "/tmp/foo.c", language = "c99"
Function: id = {0x7fffffff00000032}, name = "main", range = [0x0000000100003f60-0x0000000100003f8a)
FuncType: id = {0x7fffffff00000032}, byte-size = 0, decl = foo.c:4, compiler_type = "int (void)"
Blocks: id = {0x7fffffff00000032}, range = [0x100003f60-0x100003f8a)
LineEntry: [0x0000000100003f6f-0x0000000100003f82): /tmp/foo.c:6:3
Symbol: id = {0x00000005}, range = [0x0000000100003f60-0x0000000100003f8a), name="main"
You can also write a lldb command in Python that wraps this bit of business, which would make it easier to use. Details on that are here:
https://lldb.llvm.org/use/python-reference.html#create-a-new-lldb-command-using-a-python-function
You could even do a hybrid approach, and make all the lldb work you want to do a custom Python command. That would allow you to use the lldb Python API's to get what info you needed and write it out in whatever format is convenient for you, and would simplify the lldb invocation in your shell script and facilitate recovering the information lldb provided...

How to pass command line arguments to Deno?

I have a Deno app, that I wish to pass some command line args to. I searched the manual, but found nothing.
I tried to use the same commands used in Node.js, assuming they might be sharing some for the std libraries, but it didn't work as well.
var args = process.argv.slice(2);
// Uncaught ReferenceError: process is not defined
Any suggestions?
You can access arguments by using Deno.args, it will contain an array of the arguments passed to that script.
// deno run args.js one two three
console.log(Deno.args); // ['one, 'two', 'three']
If you want to parse those arguments you can use std/flags, which will parse the arguments similar to minimist
import { parse } from "https://deno.land/std/flags/mod.ts";
console.log(parse(Deno.args))
If you call it with:
deno run args.js -h 1 -w on
You'll get
{ _: [], h: 1, w: "on" }
You can use Deno.args to access the command line arguments in Deno.
To try it create a file test.ts :
console.log(Deno.args);
And run it with deno run test.ts firstArgument secondArgument
It will return you with an array of the passed args:
$ deno run test.ts firstArgument secondArgument
[ "firstArgument", "secondArgument" ]
If you take a stroll through the standard library, you will find a library named flags, which sounds like it could be library for command line parsing. In the README, you will find your answer in the very first line:
const { args } = Deno;
Also, if you look at the Deno Manual, specifically the Examples section, you will find numerous examples of command line example programs that perform argument parsing, for example, a clone of the Unix cat command (which is also included in the First Steps section of the Deno Manual), where you will also find your answer in the first line:
for (let i = 0; i < Deno.args.length; i++)
So, in short: the command line arguments are a property of the global Deno object, which is documented here:
const Deno.args: string[]
Returns the script arguments to the program. If for example we run a program:
deno run --allow-read https://deno.land/std/examples/cat.ts /etc/passwd
Then Deno.args will contain:
[ "/etc/passwd" ]
Note: According to the Manual, all non-web APIs are under the global Deno namespace.

Ruby - Running rb file from script [duplicate]

This question already has answers here:
Running another ruby script from a ruby script
(7 answers)
Closed 7 years ago.
I'd like to write a ruby script that then calls another ruby script.
Example, I'd like to run the "test1.rb" from my script.
The test1.rb has been simplified to just do this:
print "1"
Then get the result (-> 1).
I tried to complete this problem with backticks or another executing command (%x[#{"test1.rb"}], system("test1.rb") etc.), but it didn't work.
So any idea how I call one script that then calls another script (either relinquishing total control or forking), and get the results?
Thanks
You can simply require the file, which would load the code and execute it:
require_relative "path/test1"
For the sake of having controll over the the run code, I would advice to place your script in a method:
# In test1.rb
def exec_my_script
puts 1
end
# In your main script
require_relative "path/test1"
exec_my_script
EDIT: Ok, since this does not seem to work for your usecase, you can read the file as string and eval the string as so:
result = eval(File.read("path/test1.rb"))
# do something with result
I do NOT like this approach, because it feels kinda "hacky" and is by all means insecure and it will only work if the last thing called in your test1 script returns the result you need...
You may want to use open3
require 'open3'
cmd = 'ruby test1.rb'
#You may change the contents of cmd like you would run it from the command line; like ruby [directory]/filename
Open3.popen3(cmd) do |stdin, stdout|
var = stdout.read
puts var
end
system('ruby test1.rb') # should do the trick
You can also make test1 executable (with chmod) and add the shebang line on top of test1.
You then can call
system("./test1.rb")
Ok, the system('ruby test1.rb') and system("ruby", "test1.rb") command worked.
And now, I like to set the returning value ("1") to a variable.
How I do it? It's possible to do that with backticks?

Python: Call a shell script which calls a bin. With arguments

The context: There is a map somewhere on the system with bin files which I'd like to call. They are not callable directly though, but through shell scripts which do all kinds of magic and then call the corresponding bin with: "$ENV_VAR/path/to/the/bin" "$#" (the software is non-free, that's probably why this construction is used)
The problem: Calling this from within Python. I tried to use:
from subprocess import call
call(["nameOfBin", "-input somefile"])
But this gave the error ERROR: nameOfBin - Illegal option: input somefile. This means the '-' sign in front of 'input' has disapeared along the way (putting more '-' signs in front doesn't help).
Possible solutions:
1: In some way preserving the '-' sign so the bin at the end actually takes '-input' as an option instead of 'input'.
2: Fix the magic in a dirty way (I will probably manage), and have a way to call a bin at a location defined by a $ENV_VAR (environment variable).
I searched for both methods, but appearantly nobody before me had such a problem (or I didn't see it: Sorry if that's the case).
Each item in the list should be a single argument. Replace "-input somefile" with "-input", "somefile":
from subprocess import call
rc = call(["nameOfBin", "-input", "somefile"])

Resources