-
Notifications
You must be signed in to change notification settings - Fork 780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Arguments are not working with 'textual run' #1064
Comments
The issue here is the bit of code towards the end: if __name__ == "__main__":
if len(argv) > 1:
app = MyApp(argv[1])
else:
app = MyApp()
app.run() The However, even if you were to do that, I suspect it won't have the effect you're hoping for. As you may imagine, if you're going to But there is a different approach you can take. Rather than using So, for example, in one terminal you can do: $ textual console to get the developer console up and running, and then in another do something like (depending on shell): $ export TEXTUAL=devtools python ./sample.py. foo and everything should work as you were hoping. Let me know how you get on and if this solves the issue for you. |
A `textual run` already made an attempt to monkey-patch `argv` so that the application being run would not see an `argv` any differently to how it would if it had been run "vanilla". However, it could be caught out by code like: from sys import argv ... do_something_with( argv ) beforehand it was okay with: import sys ... do_something_with( sys.argv ) With this change it should work both ways. Somewhat related to Textualize#1064.
My code was simply for example to simulate passing arguments to a script via command line (which would start execution at the global/main scope.) As the Setting the TEXTUAL environment variable does indeed allow the console to work without Looking at _import_app.py, it appears that the code extracts out the arguments with the shlex.split:
And then assigns them into the global_vars, but only if sys is one of the returned global_variable from runpy.run_path (which from my testing never seems to get returned in the global_vars)
It then appears that nothing is ever done with the "sys" key regardless. Perhaps argument handling is still a work-in-progress? |
There's a fix for this in master. |
Did we solve your problem? Glad we could help! |
Thanks for the quick response. This is still not solving my concern on what is the right way to get arguments in to the app from What I would expect would be for both
|
I suspect there's a couple of things at play here, so I'll try as best as I can to explain things exactly how I see them and how I'd document them, so do forgive me if I state the very obvious as I do this. So, first up, as I understood it, #1030 was very much a question of "what is the best way to pass arguments into an instance of my application class"; while it did also include getting arguments from the command line, that seemed to be more of an implementation detail for a developer. So, to take the example I used over there, this code: from textual.app import App, ComposeResult
from textual.widgets import Static
class Greetings(App[None]):
def __init__(self, greeting: str="Hello", to_greet: str="World") -> None:
self.greeting = greeting
self.to_greet = to_greet
super().__init__()
def compose(self) -> ComposeResult:
yield Static(f"{self.greeting}, {self.to_greet}")
if __name__=="__main__":
Greetings().run()
Greetings(to_greet="davep").run()
Greetings("Well hello", "there").run() runs 3 different instances of my app, one after the other, passing different values to it. In this case I'm hard-coding them in the code itself, but I could just have easily pulled them out of Now, so far, this is all expecting that the code will be run as So then we get to In this case I see you having a couple of options, both of each really come down to your own design choices. The first is that, if your app is going to be totally driven by values coming off the command line, it might make more sense to place the The other option, as mentioned earlier, would be to code your app as if it were being run standalone, without being run using Admittedly I'm fairly fresh to this, so perhaps @willmcgugan will clarify if I'm off a little here, but from my own perspective I view In summary:
They kind of can't because the former will be running the code that's guarded by For what you want to do, I'd say that the $ python ./sample.py foobar is this: $ TEXTUAL=devtools python ./sample.py foobar Apologies if that rambles a wee bit, I was hoping to cover all the options. Does that help? |
Thanks, I truly appreciate the discussion. It would be really good to add TEXTUAL=devtools to the documentation, I agree that is probably the best way to debug if the code has any logic outside of the App instance. I think the other thing that I found confusing is the output of
"If you are running a file and want to pass command line arguments" - I think could be easily interpreted that it would call the code the same way as it does when running the file from the command line (e.g. the fairly typical model when running a file that execution starts with Again, the TEXTUAL=devtools does seem to be the most flexible, any reason to not do this all the time? Is there any particular benefit from running textual console? |
I would imagine that most people will find out about I'll make a note about ensuring that the environment variable gets clearly mentioned in the docs. |
Per
textual run --help
:This is not working. Using the following sample.py:
When run via:
python ./sample.py foo
it returns a textual window with
foo
When run via:
textual run "./sample.py foo"
it returns a textual window with
default
The text was updated successfully, but these errors were encountered: