Elixir:如何正确描述mix.exs设置?

时间:2015-07-20 00:11:40

标签: elixir mix

我尝试使用HTTPoison编写Web抓取工具。作为第一步,我按照下面显示的步骤编写了一个简短的HTTP访问代码;

  1. 通过mix

    创建项目

    $ mix new httptest1

  2. 在lib / httptest1.ex上写一个简短的代码。

    defmodule Httptest1 do
      require HTTPoison
    
      def test1 do
        ret = HTTPoison.get! "http://www.yahoo.com"
        %HTTPoison.Response{status_code: 200, body: body} = ret
        IO.inspect body
      end
    end
    
    Httptest1.test1()
    
  3. 修改HTTP.ison的mix.exs。

    defmodule Httptest1.Mixfile do
      use Mix.Project
    
      def project do
        [app: :httptest1,
         version: "0.0.1",
         elixir: "~> 1.0",
         build_embedded: Mix.env == :prod,
         start_permanent: Mix.env == :prod,
         deps: deps]
      end
    
      # Configuration for the OTP application
      def application do
        [applications: [:logger, :httpoison]]
      end
    
      # Dependencies can be Hex packages:
      #
      defp deps do
        [
         {:httpoison, "~> 0.6"}
        ]
      end
    end
    
  4. 运行$ mix deps.get以获取相关性。

  5. 运行$ mix run,然后编译失败;

    ==> idna (compile)
    Compiled src/idna.erl
    Compiled src/idna_ucs.erl
    Compiled src/punycode.erl
    (... snip ...)
    Generated httpoison app
    
    == Compilation error on file lib/httptest1.ex ==
    ** (exit) exited in: :gen_server.call(:hackney_manager, {:new_request, #PID<0.154.0>, #Reference<0.0.1.1724>, {:client, :undefined, :hackney_dummy_metrics, :hackney_tcp_transport, 'www.yahoo.com', 80, "www.yahoo.com", [connect_timeout: 5000, recv_timeout: :infinity], nil, nil, nil, true, :hackney_pool, :infinity, false, 5, false, 5, nil, nil, nil, :undefined, :start, nil, :normal, false, false, false, false, nil, :waiting, nil, 4096, "", [], :undefined, nil, nil, nil, nil, :undefined, nil}}, :infinity)
        ** (EXIT) no process
        (stdlib) gen_server.erl:212: :gen_server.call/3
        src/hackney_client/hackney_manager.erl:66: :hackney_manager.init_request/1
        src/hackney_client/hackney_manager.erl:56: :hackney_manager.new_request/1
        src/hackney_connect/hackney_connect.erl:181: :hackney_connect.socket_from_pool/4
        src/hackney_connect/hackney_connect.erl:36: :hackney_connect.connect/5
        src/hackney_client/hackney.erl:319: :hackney.request/5
        lib/httpoison.ex:60: HTTPoison.request/5
        lib/httpoison.ex:60: HTTPoison.request!/5
    
  6. 当我使用$ iex -S mix时,结果是相同的。

    但是,如果我将httptest1.ex移动到放置了mix.exs的同一目录,例如$ mv lib/httptest1.ex .,并尝试明确指定源文件; $ mix run httptest1,它运作正常。

    问题: 我怀疑我的mix.exs设置有问题,那是什么?

2 个答案:

答案 0 :(得分:2)

.ex中的所有lib/都已编译完毕。由于Elixir是编译文件时的元编程语言,因此实际上是在运行代码。这意味着在编译项目时会执行Httptest1.test1()

需要启动HTTPoison才能正常工作。它是在您的应用程序启动时启动的,当您执行mix run ...时。但是当您的项目正在编译项目或者您的依赖项未启动时,对依赖项的调用可能会失败。

在入门指南中查看本章Supervisor and Application,了解如何在应用程序启动时运行代码。

答案 1 :(得分:0)

改进!现在我知道如何创建可执行的调用命令行。

方案;

defmodule Httptest1 do
  use Application
  require HTTPoison

  def start(_type, _args) do
    import Supervisor.Spec, warn: false
    children = []
    opts = [strategy: :one_for_one, name: Httptest1.Supervisor]
    Supervisor.start_link(children, opts)
  end

  def main(args) do # entry point
    ret = HTTPoison.get! "http://www.yahoo.com"
    %HTTPoison.Response{status_code: _, body: body} = ret # no status code matching now
    IO.inspect body
  end

end

和mix.exs(均由$ mix new httptest1 --sup主管选项创建);

defmodule Httptest1.Mixfile do
  use Mix.Project

  def project do
    [app: :httptest1,
     version: "0.0.1",
     elixir: "~> 1.0",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     escript: escript,  # <<<< Added 
     deps: deps]
  end

  def escript do # define escript 
    [main_module: Httptest1]
  end

  def application do
    [applications: [:logger, :httpoison],
     mod: {Httptest1, []}] # 
  end

  defp deps do
    [
      {:httpoison, "~> 0.6"}
    ]
  end
end

然后在$ iex -S mix类型Httptest.test1调用的iex中,预期的结果出现了!感谢。

另外,要创建命令行可执行文件,

   $ mix escript.build

然后生成./httptest1。完成。