Repository: gaogaotiantian/coredumpy

Issue:
如何在使用argparse的同时使用coredumpy？
您好，原本，我的python代码需要通过以下bash脚本运行。
```bash
export PYTHONPATH=./
python ./src/run_experiment.py --config_path configs/assignments/examples/llama31_8b_instruct/instance/db_bench/instance/group_self_consistency_first50.yaml
```
但是，当我想在项目中加入coredumpy中后，我发现coredumpy无法识别参数`config_path`。
```bash
coredumpy run ./src/run_experiment.py --config_path configs/assignments/examples/llama31_8b_instruct/instance/db_bench/instance/group_self_consistency_first50.yaml
usage: coredumpy [-h] {run,load,peek,host} ...
coredumpy: error: unrecognized arguments: --config_path configs/assignments/examples/llama31_8b_instruct/instance/db_bench/instance/group_self_consistency_first50.yaml
```
另，我已经在代码中通过`coredumpy.patch_except(path_config.coredumpy_output_dir)`指定了coredumpy的输出文件夹，但是直接使用python运行文件，抛出异常时似乎不会生成dump。

Discussion:
@gaogaotiantian: 前面那个问题是我的问题，总是忘了argument的事情，这两天我会patch一下。

但是`patch_except`不工作是不应该的，如果它不工作那`coredumpy run`也不会有用因为机制是一样的。你需要做一个reproducible example否则我也没法查是什么问题。有几种可能性，比如你override了exception的handling，或者这个exception是在另一个process抛出的，或者你其实catch了这个exception然后正常退出了之类的。@gaogaotiantian: #81 把这个标题的内容fix了，你那个except没法catch的问题，如果有复现的example，可以另开一个issue，或者把这个issue标题改一下然后reopen。

Solution patch:
diff --git a/src/coredumpy/coredumpy.py b/src/coredumpy/coredumpy.py
index 6f09a3a..c4a61b2 100644
--- a/src/coredumpy/coredumpy.py
+++ b/src/coredumpy/coredumpy.py
@@ -333,18 +333,18 @@ class Coredumpy:
             print(textwrap.indent(data["description"], "    "))
 
     @classmethod
-    def run(cls, options):
+    def run(cls, options, args):
         if options.module:
             file = options.module
             target = _ModuleTarget(file)
         else:
-            if not options.args:
+            if not args:
                 print("Error: no script specified")
                 sys.exit(1)
-            file = options.args.pop(0)
+            file = args.pop(0)
             target = _ScriptTarget(file)
 
-        sys.argv[:] = [file] + options.args
+        sys.argv[:] = [file] + args
 
         import __main__
         __main__.__dict__.clear()
diff --git a/src/coredumpy/main.py b/src/coredumpy/main.py
index 010c247..59f003c 100644
--- a/src/coredumpy/main.py
+++ b/src/coredumpy/main.py
@@ -18,7 +18,6 @@ def main():
     subparsers_run.add_argument("--path", help="The path of dump file", default=None)
     subparsers_run.add_argument("--directory", help="The directory of dump file", default=None)
     subparsers_run.add_argument("--conf", help="The startup configuration file to run", default=None)
-    subparsers_run.add_argument("args", nargs="*")
 
     subparsers_load = subparsers.add_parser("load", help="Load a dump file.")
     subparsers_load.add_argument("file", type=str, help="The dump file to load.")
@@ -31,19 +30,19 @@ def main():
     subparsers_host = subparsers.add_parser("host", help="Host a DAP server.")
     subparsers_host.add_argument("--conf", help="The startup configuration file to run", default=None)
 
-    args = parser.parse_args()
+    options, args = parser.parse_known_args()
 
-    if hasattr(args, "conf") and args.conf and os.path.exists(args.conf):
-        runpy.run_path(args.conf)
+    if hasattr(options, "conf") and options.conf and os.path.exists(options.conf):
+        runpy.run_path(options.conf)
 
-    if args.command == "load":
-        if os.path.exists(args.file):
-            debugger = "ipdb" if args.ipdb else "pdb"
-            load(args.file, debugger=debugger)
+    if options.command == "load":
+        if os.path.exists(options.file):
+            debugger = "ipdb" if options.ipdb else "pdb"
+            load(options.file, debugger=debugger)
         else:
-            print(f"File {args.file} not found.")
-    elif args.command == "peek":
-        for file in args.files:
+            print(f"File {options.file} not found.")
+    elif options.command == "peek":
+        for file in options.files:
             if os.path.exists(file):
                 if os.path.isdir(file):
                     for f in os.listdir(file):
@@ -59,7 +58,7 @@ def main():
                         pass
             else:
                 print(f"File {file} not found.")
-    elif args.command == "run":
-        run(args)
-    elif args.command == "host":
+    elif options.command == "run":
+        run(options, args)
+    elif options.command == "host":
         host()


Test patch:
diff --git a/tests/test_basic.py b/tests/test_basic.py
index 5f0bb9d..d4a1337 100644
--- a/tests/test_basic.py
+++ b/tests/test_basic.py
@@ -6,6 +6,7 @@ import contextlib
 import io
 import os
 import tempfile
+import textwrap
 
 from .base import TestBase
 
@@ -280,6 +281,25 @@ class TestBasic(TestBase):
             stdout, _ = self.run_peek([os.path.join(tmpdir, "nosuchfile")])
             self.assertIn("not found", stdout)
 
+    def test_script_with_options(self):
+        # Test script with options
+        script = textwrap.dedent("""
+            import sys
+            print(sys.argv[1:])
+        """)
+        with tempfile.TemporaryDirectory() as tmpdir:
+            with open(f"{tmpdir}/script.py", "w", encoding="utf-8") as f:
+                f.write(script)
+
+            stdout, _ = self.run_run([f"{tmpdir}/script.py", "arg1", "arg2"])
+            self.assertIn("['arg1', 'arg2']", stdout)
+
+            stdout, _ = self.run_run([f"{tmpdir}/script.py", "--test", "-k"])
+            self.assertIn("['--test', '-k']", stdout)
+
+            stdout, _ = self.run_run([f"{tmpdir}/script.py", "--", "-m", "module", "--path", "path"])
+            self.assertIn("['--', '-m', 'module', '--path', 'path']", stdout)
+
     def test_nonexist_file(self):
         stdout, stderr = self.run_test("", "nonexist_dump", [])
         self.assertIn("File nonexist_dump not found", stdout)